# console_cmds.cpp

Go to the documentation of this file.

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