console_cmds.cpp

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

Generated on Wed Feb 17 23:06:45 2010 for OpenTTD by  doxygen 1.6.1