console_cmds.cpp

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

Generated on Mon Feb 16 23:12:06 2009 for openttd by  doxygen 1.5.6