console_cmds.cpp

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

Generated on Sun Sep 13 08:19:15 2009 for OpenTTD by  doxygen 1.5.6