# console_cmds.cpp

Go to the documentation of this file.

    00001 /* $Id: console_cmds.cpp 13689 2008-07-09 19:30:44Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "console.h"
    00008 #include "debug.h"
    00009 #include "engine.h"
    00010 #include "landscape.h"
    00011 #include "saveload.h"
    00012 #include "variables.h"
    00013 #include "network/network_data.h"
    00014 #include "network/network_client.h"
    00015 #include "network/network_server.h"
    00016 #include "network/network_udp.h"
    00017 #include "command_func.h"
    00018 #include "settings_func.h"
    00019 #include "fios.h"
    00020 #include "fileio.h"
    00021 #include "station.h"
    00022 #include "screenshot.h"
    00023 #include "genworld.h"
    00024 #include "network/network.h"
    00025 #include "strings_func.h"
    00026 #include "viewport_func.h"
    00027 #include "window_func.h"
    00028 #include "functions.h"
    00029 #include "map_func.h"
    00030 #include "date_func.h"
    00031 #include "vehicle_func.h"
    00032 #include "string_func.h"
    00033 #include "player_func.h"
    00034 #include "player_base.h"
    00035 #include "settings_type.h"
    00036
    00037 #ifdef ENABLE_NETWORK
    00038   #include "table/strings.h"
    00039 #endif /* ENABLE_NETWORK */
    00040
    00041 // ** scriptfile handling ** //
    00042 static FILE *_script_file;
    00043 static bool _script_running;
    00044
    00045 // ** console command / variable defines ** //
    00046 #define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
    00047 #define DEF_CONSOLE_HOOK(function) static bool function()
    00048
    00049
    00050 /* **************************** */
    00051 /* variable and command hooks   */
    00052 /* **************************** */
    00053
    00054 #ifdef ENABLE_NETWORK
    00055
    00056 static inline bool NetworkAvailable()
    00057 {
    00058   if (!_network_available) {
    00059     IConsoleError("You cannot use this command because there is no network available.");
    00060     return false;
    00061   }
    00062   return true;
    00063 }
    00064
    00065 DEF_CONSOLE_HOOK(ConHookServerOnly)
    00066 {
    00067   if (!NetworkAvailable()) return false;
    00068
    00069   if (!_network_server) {
    00070     IConsoleError("This command/variable is only available to a network server.");
    00071     return false;
    00072   }
    00073   return true;
    00074 }
    00075
    00076 DEF_CONSOLE_HOOK(ConHookClientOnly)
    00077 {
    00078   if (!NetworkAvailable()) return false;
    00079
    00080   if (_network_server) {
    00081     IConsoleError("This command/variable is not available to a network server.");
    00082     return false;
    00083   }
    00084   return true;
    00085 }
    00086
    00087 DEF_CONSOLE_HOOK(ConHookNeedNetwork)
    00088 {
    00089   if (!NetworkAvailable()) return false;
    00090
    00091   if (!_networking) {
    00092     IConsoleError("Not connected. This command/variable is only available in multiplayer.");
    00093     return false;
    00094   }
    00095   return true;
    00096 }
    00097
    00098 DEF_CONSOLE_HOOK(ConHookNoNetwork)
    00099 {
    00100   if (_networking) {
    00101     IConsoleError("This command/variable is forbidden in multiplayer.");
    00102     return false;
    00103   }
    00104   return true;
    00105 }
    00106
    00107 #endif /* ENABLE_NETWORK */
    00108
    00109 static void IConsoleHelp(const char *str)
    00110 {
    00111   IConsolePrintF(_icolour_warn, "- %s", str);
    00112 }
    00113
    00114 DEF_CONSOLE_CMD(ConResetEngines)
    00115 {
    00116   if (argc == 0) {
    00117     IConsoleHelp("Reset status data of all engines. This might solve some issues with 'lost' engines. Usage: 'resetengines'");
    00118     return true;
    00119   }
    00120
    00121   StartupEngines();
    00122   return true;
    00123 }
    00124
    00125 #ifdef _DEBUG
    00126 DEF_CONSOLE_CMD(ConResetTile)
    00127 {
    00128   if (argc == 0) {
    00129     IConsoleHelp("Reset a tile to bare land. Usage: 'resettile <tile>'");
    00130     IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
    00131     return true;
    00132   }
    00133
    00134   if (argc == 2) {
    00135     uint32 result;
    00136     if (GetArgumentInteger(&result, argv[1])) {
    00137       DoClearSquare((TileIndex)result);
    00138       return true;
    00139     }
    00140   }
    00141
    00142   return false;
    00143 }
    00144
    00145 DEF_CONSOLE_CMD(ConStopAllVehicles)
    00146 {
    00147   if (argc == 0) {
    00148     IConsoleHelp("Stops all vehicles in the game. For debugging only! Use at your own risk... Usage: 'stopall'");
    00149     return true;
    00150   }
    00151
    00152   StopAllVehicles();
    00153   return true;
    00154 }
    00155 #endif /* _DEBUG */
    00156
    00157 DEF_CONSOLE_CMD(ConScrollToTile)
    00158 {
    00159   if (argc == 0) {
    00160     IConsoleHelp("Center the screen on a given tile. Usage: 'scrollto <tile>'");
    00161     IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
    00162     return true;
    00163   }
    00164
    00165   if (argc == 2) {
    00166     uint32 result;
    00167     if (GetArgumentInteger(&result, argv[1])) {
    00168       if (result >= MapSize()) {
    00169         IConsolePrint(_icolour_err, "Tile does not exist");
    00170         return true;
    00171       }
    00172       ScrollMainWindowToTile((TileIndex)result);
    00173       return true;
    00174     }
    00175   }
    00176
    00177   return false;
    00178 }
    00179
    00180 extern void BuildFileList();
    00181 extern void SetFiosType(const byte fiostype);
    00182
    00183 /* Save the map to a file */
    00184 DEF_CONSOLE_CMD(ConSave)
    00185 {
    00186   if (argc == 0) {
    00187     IConsoleHelp("Save the current game. Usage: 'save <filename>'");
    00188     return true;
    00189   }
    00190
    00191   if (argc == 2) {
    00192     char *filename = str_fmt("%s.sav", argv[1]);
    00193     IConsolePrint(_icolour_def, "Saving map...");
    00194
    00195     if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
    00196       IConsolePrint(_icolour_err, "Saving map failed");
    00197     } else {
    00198       IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", filename);
    00199     }
    00200     free(filename);
    00201     return true;
    00202   }
    00203
    00204   return false;
    00205 }
    00206
    00207 /* Explicitly save the configuration */
    00208 DEF_CONSOLE_CMD(ConSaveConfig)
    00209 {
    00210   if (argc == 0) {
    00211     IConsoleHelp("Saves the current config, typically to 'openttd.cfg'.");
    00212     return true;
    00213   }
    00214
    00215   SaveToConfig();
    00216   IConsolePrint(_icolour_def, "Saved config.");
    00217   return true;
    00218 }
    00219
    00220 static const FiosItem* GetFiosItem(const char* file)
    00221 {
    00222   int i;
    00223
    00224   _saveload_mode = SLD_LOAD_GAME;
    00225   BuildFileList();
    00226
    00227   for (i = 0; i < _fios_num; i++) {
    00228     if (strcmp(file, _fios_list[i].name) == 0) break;
    00229     if (strcmp(file, _fios_list[i].title) == 0) break;
    00230   }
    00231
    00232   if (i == _fios_num) { // If no name matches, try to parse it as number
    00233     char* endptr;
    00234
    00235     i = strtol(file, &endptr, 10);
    00236     if (file == endptr || *endptr != '\0') i = -1;
    00237   }
    00238
    00239   return IsInsideMM(i, 0, _fios_num) ? &_fios_list[i] : NULL;
    00240 }
    00241
    00242
    00243 DEF_CONSOLE_CMD(ConLoad)
    00244 {
    00245   const FiosItem *item;
    00246   const char *file;
    00247
    00248   if (argc == 0) {
    00249     IConsoleHelp("Load a game by name or index. Usage: 'load <file | number>'");
    00250     return true;
    00251   }
    00252
    00253   if (argc != 2) return false;
    00254
    00255   file = argv[1];
    00256   item = GetFiosItem(file);
    00257   if (item != NULL) {
    00258     switch (item->type) {
    00259       case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: {
    00260         _switch_mode = SM_LOAD;
    00261         SetFiosType(item->type);
    00262
    00263         ttd_strlcpy(_file_to_saveload.name, FiosBrowseTo(item), sizeof(_file_to_saveload.name));
    00264         ttd_strlcpy(_file_to_saveload.title, item->title, sizeof(_file_to_saveload.title));
    00265       } break;
    00266       default: IConsolePrintF(_icolour_err, "%s: Not a savegame.", file);
    00267     }
    00268   } else {
    00269     IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
    00270   }
    00271
    00272   FiosFreeSavegameList();
    00273   return true;
    00274 }
    00275
    00276
    00277 DEF_CONSOLE_CMD(ConRemove)
    00278 {
    00279   const FiosItem* item;
    00280   const char* file;
    00281
    00282   if (argc == 0) {
    00283     IConsoleHelp("Remove a savegame by name or index. Usage: 'rm <file | number>'");
    00284     return true;
    00285   }
    00286
    00287   if (argc != 2) return false;
    00288
    00289   file = argv[1];
    00290   item = GetFiosItem(file);
    00291   if (item != NULL) {
    00292     if (!FiosDelete(item->name))
    00293       IConsolePrintF(_icolour_err, "%s: Failed to delete file", file);
    00294   } else {
    00295     IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
    00296   }
    00297
    00298   FiosFreeSavegameList();
    00299   return true;
    00300 }
    00301
    00302
    00303 /* List all the files in the current dir via console */
    00304 DEF_CONSOLE_CMD(ConListFiles)
    00305 {
    00306   int i;
    00307
    00308   if (argc == 0) {
    00309     IConsoleHelp("List all loadable savegames and directories in the current dir via console. Usage: 'ls | dir'");
    00310     return true;
    00311   }
    00312
    00313   BuildFileList();
    00314
    00315   for (i = 0; i < _fios_num; i++) {
    00316     const FiosItem *item = &_fios_list[i];
    00317     IConsolePrintF(_icolour_def, "%d) %s", i, item->title);
    00318   }
    00319
    00320   FiosFreeSavegameList();
    00321   return true;
    00322 }
    00323
    00324 /* Change the dir via console */
    00325 DEF_CONSOLE_CMD(ConChangeDirectory)
    00326 {
    00327   const FiosItem *item;
    00328   const char *file;
    00329
    00330   if (argc == 0) {
    00331     IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
    00332     return true;
    00333   }
    00334
    00335   if (argc != 2) return false;
    00336
    00337   file = argv[1];
    00338   item = GetFiosItem(file);
    00339   if (item != NULL) {
    00340     switch (item->type) {
    00341       case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
    00342         FiosBrowseTo(item);
    00343         break;
    00344       default: IConsolePrintF(_icolour_err, "%s: Not a directory.", file);
    00345     }
    00346   } else {
    00347     IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
    00348   }
    00349
    00350   FiosFreeSavegameList();
    00351   return true;
    00352 }
    00353
    00354 DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
    00355 {
    00356   const char *path;
    00357
    00358   if (argc == 0) {
    00359     IConsoleHelp("Print out the current working directory. Usage: 'pwd'");
    00360     return true;
    00361   }
    00362
    00363   // XXX - Workaround for broken file handling
    00364   FiosGetSavegameList(SLD_LOAD_GAME);
    00365   FiosFreeSavegameList();
    00366
    00367   FiosGetDescText(&path, NULL);
    00368   IConsolePrint(_icolour_def, path);
    00369   return true;
    00370 }
    00371
    00372 DEF_CONSOLE_CMD(ConClearBuffer)
    00373 {
    00374   if (argc == 0) {
    00375     IConsoleHelp("Clear the console buffer. Usage: 'clear'");
    00376     return true;
    00377   }
    00378
    00379   IConsoleClearBuffer();
    00380   InvalidateWindow(WC_CONSOLE, 0);
    00381   return true;
    00382 }
    00383
    00384
    00385 // ********************************* //
    00386 // * Network Core Console Commands * //
    00387 // ********************************* //
    00388 #ifdef ENABLE_NETWORK
    00389
    00390 DEF_CONSOLE_CMD(ConBan)
    00391 {
    00392   NetworkClientInfo *ci;
    00393   const char *banip = NULL;
    00394   uint32 index;
    00395
    00396   if (argc == 0) {
    00397     IConsoleHelp("Ban a player from a network game. Usage: 'ban <ip | client-id>'");
    00398     IConsoleHelp("For client-id's, see the command 'clients'");
    00399     IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
    00400     return true;
    00401   }
    00402
    00403   if (argc != 2) return false;
    00404
    00405   if (strchr(argv[1], '.') == NULL) { // banning with ID
    00406     index = atoi(argv[1]);
    00407     ci = NetworkFindClientInfoFromIndex(index);
    00408   } else { // banning IP
    00409     ci = NetworkFindClientInfoFromIP(argv[1]);
    00410     if (ci == NULL) {
    00411       banip = argv[1];
    00412       index = (uint32)-1;
    00413     } else {
    00414       index = ci->client_index;
    00415     }
    00416   }
    00417
    00418   if (index == NETWORK_SERVER_INDEX) {
    00419     IConsoleError("Silly boy, you can not ban yourself!");
    00420     return true;
    00421   }
    00422
    00423   if (index == 0 || (ci == NULL && index != (uint32)-1)) {
    00424     IConsoleError("Invalid client");
    00425     return true;
    00426   }
    00427
    00428   if (ci != NULL) {
    00429     IConsolePrint(_icolour_def, "Client banned");
    00430     banip = inet_ntoa(*(struct in_addr *)&ci->client_ip);
    00431     SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
    00432   } else {
    00433     IConsolePrint(_icolour_def, "Client not online, banned IP");
    00434   }
    00435
    00436   /* Add user to ban-list */
    00437   for (index = 0; index < lengthof(_network_ban_list); index++) {
    00438     if (_network_ban_list[index] == NULL) {
    00439       _network_ban_list[index] = strdup(banip);
    00440       break;
    00441     }
    00442   }
    00443
    00444   return true;
    00445 }
    00446
    00447 DEF_CONSOLE_CMD(ConUnBan)
    00448 {
    00449   uint i, index;
    00450
    00451   if (argc == 0) {
    00452     IConsoleHelp("Unban a player from a network game. Usage: 'unban <ip | client-id>'");
    00453     IConsoleHelp("For a list of banned IP's, see the command 'banlist'");
    00454     return true;
    00455   }
    00456
    00457   if (argc != 2) return false;
    00458
    00459   index = (strchr(argv[1], '.') == NULL) ? atoi(argv[1]) : 0;
    00460   index--;
    00461
    00462   for (i = 0; i < lengthof(_network_ban_list); i++) {
    00463     if (_network_ban_list[i] == NULL) continue;
    00464
    00465     if (strcmp(_network_ban_list[i], argv[1]) == 0 || index == i) {
    00466       free(_network_ban_list[i]);
    00467       _network_ban_list[i] = NULL;
    00468       IConsolePrint(_icolour_def, "IP unbanned.");
    00469       return true;
    00470     }
    00471   }
    00472
    00473   IConsolePrint(_icolour_def, "IP not in ban-list.");
    00474   return true;
    00475 }
    00476
    00477 DEF_CONSOLE_CMD(ConBanList)
    00478 {
    00479   uint i;
    00480
    00481   if (argc == 0) {
    00482     IConsoleHelp("List the IP's of banned clients: Usage 'banlist'");
    00483     return true;
    00484   }
    00485
    00486   IConsolePrint(_icolour_def, "Banlist: ");
    00487
    00488   for (i = 0; i < lengthof(_network_ban_list); i++) {
    00489     if (_network_ban_list[i] != NULL)
    00490       IConsolePrintF(_icolour_def, "  %d) %s", i + 1, _network_ban_list[i]);
    00491   }
    00492
    00493   return true;
    00494 }
    00495
    00496 DEF_CONSOLE_CMD(ConPauseGame)
    00497 {
    00498   if (argc == 0) {
    00499     IConsoleHelp("Pause a network game. Usage: 'pause'");
    00500     return true;
    00501   }
    00502
    00503   if (_pause_game == 0) {
    00504     DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
    00505     IConsolePrint(_icolour_def, "Game paused.");
    00506   } else {
    00507     IConsolePrint(_icolour_def, "Game is already paused.");
    00508   }
    00509
    00510   return true;
    00511 }
    00512
    00513 DEF_CONSOLE_CMD(ConUnPauseGame)
    00514 {
    00515   if (argc == 0) {
    00516     IConsoleHelp("Unpause a network game. Usage: 'unpause'");
    00517     return true;
    00518   }
    00519
    00520   if (_pause_game != 0) {
    00521     DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
    00522     IConsolePrint(_icolour_def, "Game unpaused.");
    00523   } else {
    00524     IConsolePrint(_icolour_def, "Game is already unpaused.");
    00525   }
    00526
    00527   return true;
    00528 }
    00529
    00530 DEF_CONSOLE_CMD(ConRcon)
    00531 {
    00532   if (argc == 0) {
    00533     IConsoleHelp("Remote control the server from another client. Usage: 'rcon <password> <command>'");
    00534     IConsoleHelp("Remember to enclose the command in quotes, otherwise only the first parameter is sent");
    00535     return true;
    00536   }
    00537
    00538   if (argc < 3) return false;
    00539
    00540   if (_network_server) {
    00541     IConsoleCmdExec(argv[2]);
    00542   } else {
    00543     SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
    00544   }
    00545   return true;
    00546 }
    00547
    00548 DEF_CONSOLE_CMD(ConStatus)
    00549 {
    00550   static const char* const stat_str[] = {
    00551     "inactive",
    00552     "authorizing",
    00553     "authorized",
    00554     "waiting",
    00555     "loading map",
    00556     "map done",
    00557     "ready",
    00558     "active"
    00559   };
    00560
    00561   NetworkTCPSocketHandler *cs;
    00562
    00563   if (argc == 0) {
    00564     IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
    00565     return true;
    00566   }
    00567
    00568   FOR_ALL_CLIENTS(cs) {
    00569     int lag = NetworkCalculateLag(cs);
    00570     const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
    00571     const char* status;
    00572
    00573     status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
    00574     IConsolePrintF(8, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
    00575       cs->index, ci->client_name, status, lag,
    00576       ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
    00577       GetPlayerIP(ci), ci->unique_id);
    00578   }
    00579
    00580   return true;
    00581 }
    00582
    00583 DEF_CONSOLE_CMD(ConServerInfo)
    00584 {
    00585   const NetworkGameInfo *gi;
    00586
    00587   if (argc == 0) {
    00588     IConsoleHelp("List current and maximum client/player limits. Usage 'server_info'");
    00589     IConsoleHelp("You can change these values by setting the variables 'max_clients', 'max_companies' and 'max_spectators'");
    00590     return true;
    00591   }
    00592
    00593   gi = &_network_game_info;
    00594   IConsolePrintF(_icolour_def, "Current/maximum clients:    %2d/%2d", gi->clients_on, gi->clients_max);
    00595   IConsolePrintF(_icolour_def, "Current/maximum companies:  %2d/%2d", ActivePlayerCount(), gi->companies_max);
    00596   IConsolePrintF(_icolour_def, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max);
    00597
    00598   return true;
    00599 }
    00600
    00601 DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount)
    00602 {
    00603   if (_network_game_info.clients_max > MAX_CLIENTS) {
    00604     _network_game_info.clients_max = MAX_CLIENTS;
    00605     IConsoleError("Maximum clients out of bounds, truncating to limit.");
    00606   }
    00607
    00608   return true;
    00609 }
    00610
    00611 DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount)
    00612 {
    00613   if (_network_game_info.companies_max > MAX_PLAYERS) {
    00614     _network_game_info.companies_max = MAX_PLAYERS;
    00615     IConsoleError("Maximum companies out of bounds, truncating to limit.");
    00616   }
    00617
    00618   return true;
    00619 }
    00620
    00621 DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount)
    00622 {
    00623   /* XXX see ConHookValidateMaxClientsCount */
    00624   if (_network_game_info.spectators_max > 10) {
    00625     _network_game_info.spectators_max = 10;
    00626     IConsoleError("Maximum spectators out of bounds, truncating to limit.");
    00627   }
    00628
    00629   return true;
    00630 }
    00631
    00632 DEF_CONSOLE_HOOK(ConHookCheckMinPlayers)
    00633 {
    00634   CheckMinPlayers();
    00635   return true;
    00636 }
    00637
    00638 DEF_CONSOLE_CMD(ConKick)
    00639 {
    00640   NetworkClientInfo *ci;
    00641   uint32 index;
    00642
    00643   if (argc == 0) {
    00644     IConsoleHelp("Kick a player from a network game. Usage: 'kick <ip | client-id>'");
    00645     IConsoleHelp("For client-id's, see the command 'clients'");
    00646     return true;
    00647   }
    00648
    00649   if (argc != 2) return false;
    00650
    00651   if (strchr(argv[1], '.') == NULL) {
    00652     index = atoi(argv[1]);
    00653     ci = NetworkFindClientInfoFromIndex(index);
    00654   } else {
    00655     ci = NetworkFindClientInfoFromIP(argv[1]);
    00656     index = (ci == NULL) ? 0 : ci->client_index;
    00657   }
    00658
    00659   if (index == NETWORK_SERVER_INDEX) {
    00660     IConsoleError("Silly boy, you can not kick yourself!");
    00661     return true;
    00662   }
    00663
    00664   if (index == 0) {
    00665     IConsoleError("Invalid client");
    00666     return true;
    00667   }
    00668
    00669   if (ci != NULL) {
    00670     SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
    00671   } else {
    00672     IConsoleError("Client not found");
    00673   }
    00674
    00675   return true;
    00676 }
    00677
    00678 DEF_CONSOLE_CMD(ConResetCompany)
    00679 {
    00680   const Player *p;
    00681   NetworkTCPSocketHandler *cs;
    00682   const NetworkClientInfo *ci;
    00683   PlayerID index;
    00684
    00685   if (argc == 0) {
    00686     IConsoleHelp("Remove an idle company from the game. Usage: 'reset_company <company-id>'");
    00687     IConsoleHelp("For company-id's, see the list of companies from the dropdown menu. Player 1 is 1, etc.");
    00688     return true;
    00689   }
    00690
    00691   if (argc != 2) return false;
    00692
    00693   index = (PlayerID)(atoi(argv[1]) - 1);
    00694
    00695   /* Check valid range */
    00696   if (!IsValidPlayer(index)) {
    00697     IConsolePrintF(_icolour_err, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS);
    00698     return true;
    00699   }
    00700
    00701   /* Check if company does exist */
    00702   p = GetPlayer(index);
    00703   if (!p->is_active) {
    00704     IConsoleError("Company does not exist.");
    00705     return true;
    00706   }
    00707
    00708   if (p->is_ai) {
    00709     IConsoleError("Company is owned by an AI.");
    00710     return true;
    00711   }
    00712
    00713   /* Check if the company has active players */
    00714   FOR_ALL_CLIENTS(cs) {
    00715     ci = DEREF_CLIENT_INFO(cs);
    00716     if (ci->client_playas == index) {
    00717       IConsoleError("Cannot remove company: a client is connected to that company.");
    00718       return true;
    00719     }
    00720   }
    00721   ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
    00722   if (ci->client_playas == index) {
    00723     IConsoleError("Cannot remove company: the server is connected to that company.");
    00724     return true;
    00725   }
    00726
    00727   /* It is safe to remove this company */
    00728   DoCommandP(0, 2, index, NULL, CMD_PLAYER_CTRL);
    00729   IConsolePrint(_icolour_def, "Company deleted.");
    00730
    00731   return true;
    00732 }
    00733
    00734 DEF_CONSOLE_CMD(ConNetworkClients)
    00735 {
    00736   NetworkClientInfo *ci;
    00737
    00738   if (argc == 0) {
    00739     IConsoleHelp("Get a list of connected clients including their ID, name, company-id, and IP. Usage: 'clients'");
    00740     return true;
    00741   }
    00742
    00743   FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
    00744     IConsolePrintF(8, "Client #%1d  name: '%s'  company: %1d  IP: %s",
    00745                    ci->client_index, ci->client_name,
    00746                    ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
    00747                    GetPlayerIP(ci));
    00748   }
    00749
    00750   return true;
    00751 }
    00752
    00753 DEF_CONSOLE_CMD(ConNetworkConnect)
    00754 {
    00755   char *ip;
    00756   const char *port = NULL;
    00757   const char *player = NULL;
    00758   uint16 rport;
    00759
    00760   if (argc == 0) {
    00761     IConsoleHelp("Connect to a remote OTTD server and join the game. Usage: 'connect <ip>'");
    00762     IConsoleHelp("IP can contain port and player: 'IP[[#Player]:Port]', eg: 'server.ottd.org#2:443'");
    00763     IConsoleHelp("Player #255 is spectator all others are a certain company with Company 1 being #1");
    00764     return true;
    00765   }
    00766
    00767   if (argc < 2) return false;
    00768   if (_networking) NetworkDisconnect(); // we are in network-mode, first close it!
    00769
    00770   ip = argv[1];
    00771   /* Default settings: default port and new company */
    00772   rport = NETWORK_DEFAULT_PORT;
    00773   _network_playas = PLAYER_NEW_COMPANY;
    00774
    00775   ParseConnectionString(&player, &port, ip);
    00776
    00777   IConsolePrintF(_icolour_def, "Connecting to %s...", ip);
    00778   if (player != NULL) {
    00779     _network_playas = (PlayerID)atoi(player);
    00780     IConsolePrintF(_icolour_def, "    player-no: %d", _network_playas);
    00781
    00782     /* From a user pov 0 is a new player, internally it's different and all
    00783      * players are offset by one to ease up on users (eg players 1-8 not 0-7) */
    00784     if (_network_playas != PLAYER_SPECTATOR) {
    00785       _network_playas--;
    00786       if (!IsValidPlayer(_network_playas)) return false;
    00787     }
    00788   }
    00789   if (port != NULL) {
    00790     rport = atoi(port);
    00791     IConsolePrintF(_icolour_def, "    port: %s", port);
    00792   }
    00793
    00794   NetworkClientConnectGame(ip, rport);
    00795
    00796   return true;
    00797 }
    00798
    00799 #endif /* ENABLE_NETWORK */
    00800
    00801 /* ******************************** */
    00802 /*   script file console commands   */
    00803 /* ******************************** */
    00804
    00805 DEF_CONSOLE_CMD(ConExec)
    00806 {
    00807   char cmdline[ICON_CMDLN_SIZE];
    00808   char *cmdptr;
    00809
    00810   if (argc == 0) {
    00811     IConsoleHelp("Execute a local script file. Usage: 'exec <script> <?>'");
    00812     return true;
    00813   }
    00814
    00815   if (argc < 2) return false;
    00816
    00817   _script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
    00818
    00819   if (_script_file == NULL) {
    00820     if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
    00821     return true;
    00822   }
    00823
    00824   _script_running = true;
    00825
    00826   while (_script_running && fgets(cmdline, sizeof(cmdline), _script_file) != NULL) {
    00827     /* Remove newline characters from the executing script */
    00828     for (cmdptr = cmdline; *cmdptr != '\0'; cmdptr++) {
    00829       if (*cmdptr == '\n' || *cmdptr == '\r') {
    00830         *cmdptr = '\0';
    00831         break;
    00832       }
    00833     }
    00834     IConsoleCmdExec(cmdline);
    00835   }
    00836
    00837   if (ferror(_script_file))
    00838     IConsoleError("Encountered errror while trying to read from script file");
    00839
    00840   _script_running = false;
    00841   FioFCloseFile(_script_file);
    00842   return true;
    00843 }
    00844
    00845 DEF_CONSOLE_CMD(ConReturn)
    00846 {
    00847   if (argc == 0) {
    00848     IConsoleHelp("Stop executing a running script. Usage: 'return'");
    00849     return true;
    00850   }
    00851
    00852   _script_running = false;
    00853   return true;
    00854 }
    00855
    00856 /* **************************** */
    00857 /*   default console commands   */
    00858 /* **************************** */
    00859 extern bool CloseConsoleLogIfActive();
    00860
    00861 DEF_CONSOLE_CMD(ConScript)
    00862 {
    00863   extern FILE* _iconsole_output_file;
    00864
    00865   if (argc == 0) {
    00866     IConsoleHelp("Start or stop logging console output to a file. Usage: 'script <filename>'");
    00867     IConsoleHelp("If filename is omitted, a running log is stopped if it is active");
    00868     return true;
    00869   }
    00870
    00871   if (!CloseConsoleLogIfActive()) {
    00872     if (argc < 2) return false;
    00873
    00874     IConsolePrintF(_icolour_def, "file output started to: %s", argv[1]);
    00875     _iconsole_output_file = fopen(argv[1], "ab");
    00876     if (_iconsole_output_file == NULL) IConsoleError("could not open file");
    00877   }
    00878
    00879   return true;
    00880 }
    00881
    00882
    00883 DEF_CONSOLE_CMD(ConEcho)
    00884 {
    00885   if (argc == 0) {
    00886     IConsoleHelp("Print back the first argument to the console. Usage: 'echo <arg>'");
    00887     return true;
    00888   }
    00889
    00890   if (argc < 2) return false;
    00891   IConsolePrint(_icolour_def, argv[1]);
    00892   return true;
    00893 }
    00894
    00895 DEF_CONSOLE_CMD(ConEchoC)
    00896 {
    00897   if (argc == 0) {
    00898     IConsoleHelp("Print back the first argument to the console in a given colour. Usage: 'echoc <colour> <arg2>'");
    00899     return true;
    00900   }
    00901
    00902   if (argc < 3) return false;
    00903   IConsolePrint(atoi(argv[1]), argv[2]);
    00904   return true;
    00905 }
    00906
    00907 DEF_CONSOLE_CMD(ConNewGame)
    00908 {
    00909   if (argc == 0) {
    00910     IConsoleHelp("Start a new game. Usage: 'newgame [seed]'");
    00911     IConsoleHelp("The server can force a new game using 'newgame'; any client joined will rejoin after the server is done generating the new game.");
    00912     return true;
    00913   }
    00914
    00915   StartNewGameWithoutGUI((argc == 2) ? (uint)atoi(argv[1]) : GENERATE_NEW_SEED);
    00916   return true;
    00917 }
    00918
    00919 extern void SwitchMode(int new_mode);
    00920
    00921 DEF_CONSOLE_CMD(ConRestart)
    00922 {
    00923   if (argc == 0) {
    00924     IConsoleHelp("Restart game. Usage: 'restart'");
    00925     IConsoleHelp("Restarts a game. It tries to reproduce the exact same map as the game started with.");
    00926     return true;
    00927   }
    00928
    00929   /* Don't copy the _newgame pointers to the real pointers, so call SwitchMode directly */
    00930   _patches.map_x = MapLogX();
    00931   _patches.map_y = FindFirstBit(MapSizeY());
    00932   SwitchMode(SM_NEWGAME);
    00933   return true;
    00934 }
    00935
    00936 DEF_CONSOLE_CMD(ConGetSeed)
    00937 {
    00938   if (argc == 0) {
    00939     IConsoleHelp("Returns the seed used to create this game. Usage: 'getseed'");
    00940     IConsoleHelp("The seed can be used to reproduce the exact same map as the game started with.");
    00941     return true;
    00942   }
    00943
    00944   IConsolePrintF(_icolour_def, "Generation Seed: %u", _patches.generation_seed);
    00945   return true;
    00946 }
    00947
    00948 DEF_CONSOLE_CMD(ConGetDate)
    00949 {
    00950   if (argc == 0) {
    00951     IConsoleHelp("Returns the current date (day-month-year) of the game. Usage: 'getdate'");
    00952     return true;
    00953   }
    00954
    00955   YearMonthDay ymd;
    00956   ConvertDateToYMD(_date, &ymd);
    00957   IConsolePrintF(_icolour_def, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
    00958   return true;
    00959 }
    00960
    00961
    00962 DEF_CONSOLE_CMD(ConAlias)
    00963 {
    00964   IConsoleAlias *alias;
    00965
    00966   if (argc == 0) {
    00967     IConsoleHelp("Add a new alias, or redefine the behaviour of an existing alias . Usage: 'alias <name> <command>'");
    00968     return true;
    00969   }
    00970
    00971   if (argc < 3) return false;
    00972
    00973   alias = IConsoleAliasGet(argv[1]);
    00974   if (alias == NULL) {
    00975     IConsoleAliasRegister(argv[1], argv[2]);
    00976   } else {
    00977     free(alias->cmdline);
    00978     alias->cmdline = strdup(argv[2]);
    00979   }
    00980   return true;
    00981 }
    00982
    00983 DEF_CONSOLE_CMD(ConScreenShot)
    00984 {
    00985   if (argc == 0) {
    00986     IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | no_con]'");
    00987     IConsoleHelp("'big' makes a screenshot of the whole map, 'no_con' hides the console to create the screenshot");
    00988     return true;
    00989   }
    00990
    00991   if (argc > 3) return false;
    00992
    00993   SetScreenshotType(SC_VIEWPORT);
    00994   if (argc > 1) {
    00995     if (strcmp(argv[1], "big") == 0 || (argc == 3 && strcmp(argv[2], "big") == 0))
    00996       SetScreenshotType(SC_WORLD);
    00997
    00998     if (strcmp(argv[1], "no_con") == 0 || (argc == 3 && strcmp(argv[2], "no_con") == 0))
    00999       IConsoleClose();
    01000   }
    01001
    01002   return true;
    01003 }
    01004
    01005 DEF_CONSOLE_CMD(ConInfoVar)
    01006 {
    01007   static const char *_icon_vartypes[] = {"boolean", "byte", "uint16", "uint32", "int16", "int32", "string"};
    01008   const IConsoleVar *var;
    01009
    01010   if (argc == 0) {
    01011     IConsoleHelp("Print out debugging information about a variable. Usage: 'info_var <var>'");
    01012     return true;
    01013   }
    01014
    01015   if (argc < 2) return false;
    01016
    01017   var = IConsoleVarGet(argv[1]);
    01018   if (var == NULL) {
    01019     IConsoleError("the given variable was not found");
    01020     return true;
    01021   }
    01022
    01023   IConsolePrintF(_icolour_def, "variable name: %s", var->name);
    01024   IConsolePrintF(_icolour_def, "variable type: %s", _icon_vartypes[var->type]);
    01025   IConsolePrintF(_icolour_def, "variable addr: 0x%X", var->addr);
    01026
    01027   if (var->hook.access) IConsoleWarning("variable is access hooked");
    01028   if (var->hook.pre) IConsoleWarning("variable is pre hooked");
    01029   if (var->hook.post) IConsoleWarning("variable is post hooked");
    01030   return true;
    01031 }
    01032
    01033
    01034 DEF_CONSOLE_CMD(ConInfoCmd)
    01035 {
    01036   const IConsoleCmd *cmd;
    01037
    01038   if (argc == 0) {
    01039     IConsoleHelp("Print out debugging information about a command. Usage: 'info_cmd <cmd>'");
    01040     return true;
    01041   }
    01042
    01043   if (argc < 2) return false;
    01044
    01045   cmd = IConsoleCmdGet(argv[1]);
    01046   if (cmd == NULL) {
    01047     IConsoleError("the given command was not found");
    01048     return true;
    01049   }
    01050
    01051   IConsolePrintF(_icolour_def, "command name: %s", cmd->name);
    01052   IConsolePrintF(_icolour_def, "command proc: 0x%X", cmd->proc);
    01053
    01054   if (cmd->hook.access) IConsoleWarning("command is access hooked");
    01055   if (cmd->hook.pre) IConsoleWarning("command is pre hooked");
    01056   if (cmd->hook.post) IConsoleWarning("command is post hooked");
    01057
    01058   return true;
    01059 }
    01060
    01061 DEF_CONSOLE_CMD(ConDebugLevel)
    01062 {
    01063   if (argc == 0) {
    01064     IConsoleHelp("Get/set the default debugging level for the game. Usage: 'debug_level [<level>]'");
    01065     IConsoleHelp("Level can be any combination of names, levels. Eg 'net=5 ms=4'. Remember to enclose it in \"'s");
    01066     return true;
    01067   }
    01068
    01069   if (argc > 2) return false;
    01070
    01071   if (argc == 1) {
    01072     IConsolePrintF(_icolour_def, "Current debug-level: '%s'", GetDebugString());
    01073   } else {
    01074     SetDebugString(argv[1]);
    01075   }
    01076
    01077   return true;
    01078 }
    01079
    01080 DEF_CONSOLE_CMD(ConExit)
    01081 {
    01082   if (argc == 0) {
    01083     IConsoleHelp("Exit the game. Usage: 'exit'");
    01084     return true;
    01085   }
    01086
    01087   if (_game_mode == GM_NORMAL && _patches.autosave_on_exit) DoExitSave();
    01088
    01089   _exit_game = true;
    01090   return true;
    01091 }
    01092
    01093 DEF_CONSOLE_CMD(ConPart)
    01094 {
    01095   if (argc == 0) {
    01096     IConsoleHelp("Leave the currently joined/running game (only ingame). Usage: 'part'");
    01097     return true;
    01098   }
    01099
    01100   if (_game_mode != GM_NORMAL) return false;
    01101
    01102   _switch_mode = SM_MENU;
    01103   return true;
    01104 }
    01105
    01106 DEF_CONSOLE_CMD(ConHelp)
    01107 {
    01108   if (argc == 2) {
    01109     const IConsoleCmd *cmd;
    01110     const IConsoleVar *var;
    01111     const IConsoleAlias *alias;
    01112
    01113     cmd = IConsoleCmdGet(argv[1]);
    01114     if (cmd != NULL) {
    01115       cmd->proc(0, NULL);
    01116       return true;
    01117     }
    01118
    01119     alias = IConsoleAliasGet(argv[1]);
    01120     if (alias != NULL) {
    01121       cmd = IConsoleCmdGet(alias->cmdline);
    01122       if (cmd != NULL) {
    01123         cmd->proc(0, NULL);
    01124         return true;
    01125       }
    01126       IConsolePrintF(_icolour_err, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline);
    01127       return true;
    01128     }
    01129
    01130     var = IConsoleVarGet(argv[1]);
    01131     if (var != NULL && var->help != NULL) {
    01132       IConsoleHelp(var->help);
    01133       return true;
    01134     }
    01135
    01136     IConsoleError("command or variable not found");
    01137     return true;
    01138   }
    01139
    01140   IConsolePrint(13, " ---- OpenTTD Console Help ---- ");
    01141   IConsolePrint( 1, " - variables: [command to list all variables: list_vars]");
    01142   IConsolePrint( 1, " set value with '<var> = <value>', use '++/--' to in-or decrement");
    01143   IConsolePrint( 1, " or omit '=' and just '<var> <value>'. get value with typing '<var>'");
    01144   IConsolePrint( 1, " - commands: [command to list all commands: list_cmds]");
    01145   IConsolePrint( 1, " call commands with '<command> <arg2> <arg3>...'");
    01146   IConsolePrint( 1, " - to assign strings, or use them as arguments, enclose it within quotes");
    01147   IConsolePrint( 1, " like this: '<command> \"string argument with spaces\"'");
    01148   IConsolePrint( 1, " - use 'help <command> | <variable>' to get specific information");
    01149   IConsolePrint( 1, " - scroll console output with shift + (up | down) | (pageup | pagedown))");
    01150   IConsolePrint( 1, " - scroll console input history with the up | down arrows");
    01151   IConsolePrint( 1, "");
    01152   return true;
    01153 }
    01154
    01155 DEF_CONSOLE_CMD(ConListCommands)
    01156 {
    01157   const IConsoleCmd *cmd;
    01158   size_t l = 0;
    01159
    01160   if (argc == 0) {
    01161     IConsoleHelp("List all registered commands. Usage: 'list_cmds [<pre-filter>]'");
    01162     return true;
    01163   }
    01164
    01165   if (argv[1] != NULL) l = strlen(argv[1]);
    01166
    01167   for (cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) {
    01168     if (argv[1] == NULL || strncmp(cmd->name, argv[1], l) == 0) {
    01169         IConsolePrintF(_icolour_def, "%s", cmd->name);
    01170     }
    01171   }
    01172
    01173   return true;
    01174 }
    01175
    01176 DEF_CONSOLE_CMD(ConListVariables)
    01177 {
    01178   const IConsoleVar *var;
    01179   size_t l = 0;
    01180
    01181   if (argc == 0) {
    01182     IConsoleHelp("List all registered variables. Usage: 'list_vars [<pre-filter>]'");
    01183     return true;
    01184   }
    01185
    01186   if (argv[1] != NULL) l = strlen(argv[1]);
    01187
    01188   for (var = _iconsole_vars; var != NULL; var = var->next) {
    01189     if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0)
    01190       IConsolePrintF(_icolour_def, "%s", var->name);
    01191   }
    01192
    01193   return true;
    01194 }
    01195
    01196 DEF_CONSOLE_CMD(ConListAliases)
    01197 {
    01198   const IConsoleAlias *alias;
    01199   size_t l = 0;
    01200
    01201   if (argc == 0) {
    01202     IConsoleHelp("List all registered aliases. Usage: 'list_aliases [<pre-filter>]'");
    01203     return true;
    01204   }
    01205
    01206   if (argv[1] != NULL) l = strlen(argv[1]);
    01207
    01208   for (alias = _iconsole_aliases; alias != NULL; alias = alias->next) {
    01209     if (argv[1] == NULL || strncmp(alias->name, argv[1], l) == 0)
    01210       IConsolePrintF(_icolour_def, "%s => %s", alias->name, alias->cmdline);
    01211   }
    01212
    01213   return true;
    01214 }
    01215
    01216 #ifdef ENABLE_NETWORK
    01217
    01218 DEF_CONSOLE_CMD(ConSay)
    01219 {
    01220   if (argc == 0) {
    01221     IConsoleHelp("Chat to your fellow players in a multiplayer game. Usage: 'say \"<msg>\"'");
    01222     return true;
    01223   }
    01224
    01225   if (argc != 2) return false;
    01226
    01227   if (!_network_server) {
    01228     SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
    01229   } else {
    01230     NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
    01231   }
    01232
    01233   return true;
    01234 }
    01235
    01236 DEF_CONSOLE_CMD(ConPlayers)
    01237 {
    01238   Player *p;
    01239
    01240   if (argc == 0) {
    01241     IConsoleHelp("List the in-game details of all clients connected to the server. Usage 'players'");
    01242     return true;
    01243   }
    01244   NetworkPopulateCompanyInfo();
    01245
    01246   FOR_ALL_PLAYERS(p) {
    01247     char buffer[512];
    01248
    01249     if (!p->is_active) continue;
    01250
    01251     const NetworkPlayerInfo *npi = &_network_player_info[p->index];
    01252
    01253     GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer));
    01254     IConsolePrintF(8, "#:%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",
    01255       p->index + 1, buffer, npi->company_name, p->inaugurated_year, (int64)p->player_money, (int64)p->current_loan, (int64)CalculateCompanyValue(p),
    01256       /* trains      */ npi->num_vehicle[0],
    01257       /* lorry + bus */ npi->num_vehicle[1] + npi->num_vehicle[2],
    01258       /* planes      */ npi->num_vehicle[3],
    01259       /* ships       */ npi->num_vehicle[4],
    01260       /* protected   */ StrEmpty(npi->password) ? "un" : "");
    01261   }
    01262
    01263   return true;
    01264 }
    01265
    01266 DEF_CONSOLE_CMD(ConSayPlayer)
    01267 {
    01268   if (argc == 0) {
    01269     IConsoleHelp("Chat to a certain player in a multiplayer game. Usage: 'say_player <player-no> \"<msg>\"'");
    01270     IConsoleHelp("PlayerNo is the player that plays as company <playerno>, 1 through max_players");
    01271     return true;
    01272   }
    01273
    01274   if (argc != 3) return false;
    01275
    01276   if (atoi(argv[1]) < 1 || atoi(argv[1]) > MAX_PLAYERS) {
    01277     IConsolePrintF(_icolour_def, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS);
    01278     return true;
    01279   }
    01280
    01281   if (!_network_server) {
    01282     SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2]);
    01283   } else {
    01284     NetworkServer_HandleChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
    01285   }
    01286
    01287   return true;
    01288 }
    01289
    01290 DEF_CONSOLE_CMD(ConSayClient)
    01291 {
    01292   if (argc == 0) {
    01293     IConsoleHelp("Chat to a certain player in a multiplayer game. Usage: 'say_client <client-no> \"<msg>\"'");
    01294     IConsoleHelp("For client-id's, see the command 'clients'");
    01295     return true;
    01296   }
    01297
    01298   if (argc != 3) return false;
    01299
    01300   if (!_network_server) {
    01301     SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
    01302   } else {
    01303     NetworkServer_HandleChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
    01304   }
    01305
    01306   return true;
    01307 }
    01308
    01309 DEF_CONSOLE_HOOK(ConHookServerPW)
    01310 {
    01311   if (strcmp(_network_server_password, "*") == 0) {
    01312     _network_server_password[0] = '\0';
    01313     _network_game_info.use_password = 0;
    01314   } else {
    01315     ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
    01316     _network_game_info.use_password = 1;
    01317   }
    01318
    01319   return true;
    01320 }
    01321
    01322 DEF_CONSOLE_HOOK(ConHookRconPW)
    01323 {
    01324   if (strcmp(_network_rcon_password, "*") == 0)
    01325     _network_rcon_password[0] = '\0';
    01326
    01327   ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
    01328
    01329   return true;
    01330 }
    01331
    01332 extern void HashCurrentCompanyPassword();
    01333
    01334 /* Also use from within player_gui to change the password graphically */
    01335 bool NetworkChangeCompanyPassword(byte argc, char *argv[])
    01336 {
    01337   if (argc == 0) {
    01338     if (!IsValidPlayer(_local_player)) return true; // dedicated server
    01339     IConsolePrintF(_icolour_warn, "Current value for 'company_pw': %s", _network_player_info[_local_player].password);
    01340     return true;
    01341   }
    01342
    01343   if (!IsValidPlayer(_local_player)) {
    01344     IConsoleError("You have to own a company to make use of this command.");
    01345     return false;
    01346   }
    01347
    01348   if (argc != 1) return false;
    01349
    01350   if (strcmp(argv[0], "*") == 0) argv[0][0] = '\0';
    01351
    01352   ttd_strlcpy(_network_player_info[_local_player].password, argv[0], sizeof(_network_player_info[_local_player].password));
    01353
    01354   if (!_network_server) {
    01355     SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
    01356   } else {
    01357     HashCurrentCompanyPassword();
    01358   }
    01359
    01360   IConsolePrintF(_icolour_warn, "'company_pw' changed to:  %s", _network_player_info[_local_player].password);
    01361
    01362   return true;
    01363 }
    01364
    01365 DEF_CONSOLE_HOOK(ConProcPlayerName)
    01366 {
    01367   NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
    01368
    01369   if (ci == NULL) return false;
    01370
    01371   /* Don't change the name if it is the same as the old name */
    01372   if (strcmp(ci->client_name, _network_player_name) != 0) {
    01373     if (!_network_server) {
    01374       SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
    01375     } else {
    01376       if (NetworkFindName(_network_player_name)) {
    01377         NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", _network_player_name);
    01378         ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
    01379         NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
    01380       }
    01381     }
    01382   }
    01383
    01384   return true;
    01385 }
    01386
    01387 DEF_CONSOLE_HOOK(ConHookServerName)
    01388 {
    01389   ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
    01390   return true;
    01391 }
    01392
    01393 DEF_CONSOLE_HOOK(ConHookServerAdvertise)
    01394 {
    01395   if (!_network_advertise) // remove us from advertising
    01396     NetworkUDPRemoveAdvertise();
    01397
    01398   return true;
    01399 }
    01400
    01401 DEF_CONSOLE_CMD(ConProcServerIP)
    01402 {
    01403   if (argc == 0) {
    01404     IConsolePrintF(_icolour_warn, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
    01405     return true;
    01406   }
    01407
    01408   if (argc != 1) return false;
    01409
    01410   _network_server_bind_ip = (strcmp(argv[0], "all") == 0) ? inet_addr("0.0.0.0") : inet_addr(argv[0]);
    01411   snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
    01412   IConsolePrintF(_icolour_warn, "'server_ip' changed to:  %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
    01413   return true;
    01414 }
    01415 #endif /* ENABLE_NETWORK */
    01416
    01417 DEF_CONSOLE_CMD(ConPatch)
    01418 {
    01419   if (argc == 0) {
    01420     IConsoleHelp("Change patch variables for all players. Usage: 'patch <name> [<value>]'");
    01421     IConsoleHelp("Omitting <value> will print out the current value of the patch-setting.");
    01422     return true;
    01423   }
    01424
    01425   if (argc == 1 || argc > 3) return false;
    01426
    01427   if (argc == 2) {
    01428     IConsoleGetPatchSetting(argv[1]);
    01429   } else {
    01430     uint32 val;
    01431
    01432     if (GetArgumentInteger(&val, argv[2])) {
    01433       if (!IConsoleSetPatchSetting(argv[1], val)) {
    01434         if (_network_server) {
    01435           IConsoleError("This command/variable is not available during network games.");
    01436         } else {
    01437           IConsoleError("This command/variable is only available to a network server.");
    01438         }
    01439       }
    01440     }
    01441   }
    01442
    01443   return true;
    01444 }
    01445
    01446 DEF_CONSOLE_CMD(ConListPatches)
    01447 {
    01448   if (argc == 0) {
    01449     IConsoleHelp("List patch options. Usage: 'list_patches'");
    01450     return true;
    01451   }
    01452
    01453   if (argc != 1) return false;
    01454
    01455   IConsoleListPatches();
    01456   return true;
    01457 }
    01458
    01459 DEF_CONSOLE_CMD(ConListDumpVariables)
    01460 {
    01461   const IConsoleVar *var;
    01462   size_t l = 0;
    01463
    01464   if (argc == 0) {
    01465     IConsoleHelp("List all variables with their value. Usage: 'dump_vars [<pre-filter>]'");
    01466     return true;
    01467   }
    01468
    01469   if (argv[1] != NULL) l = strlen(argv[1]);
    01470
    01471   for (var = _iconsole_vars; var != NULL; var = var->next) {
    01472     if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0)
    01473       IConsoleVarPrintGetValue(var);
    01474   }
    01475
    01476   return true;
    01477 }
    01478
    01479
    01480 #ifdef _DEBUG
    01481 /* ****************************************** */
    01482 /*  debug commands and variables */
    01483 /* ****************************************** */
    01484
    01485 static void IConsoleDebugLibRegister()
    01486 {
    01487   /* debugging variables and functions */
    01488   extern bool _stdlib_con_developer; // XXX extern in .cpp
    01489
    01490   IConsoleVarRegister("con_developer",    &_stdlib_con_developer, ICONSOLE_VAR_BOOLEAN, "Enable/disable console debugging information (internal)");
    01491   IConsoleCmdRegister("resettile",        ConResetTile);
    01492   IConsoleCmdRegister("stopall",          ConStopAllVehicles);
    01493   IConsoleAliasRegister("dbg_echo",       "echo %A; echo %B");
    01494   IConsoleAliasRegister("dbg_echo2",      "echo %!");
    01495 }
    01496 #endif
    01497
    01498 /* ****************************************** */
    01499 /*  console command and variable registration */
    01500 /* ****************************************** */
    01501
    01502 void IConsoleStdLibRegister()
    01503 {
    01504   /* stdlib */
    01505   extern byte _stdlib_developer; // XXX extern in .cpp
    01506
    01507   /* default variables and functions */
    01508   IConsoleCmdRegister("debug_level",  ConDebugLevel);
    01509   IConsoleCmdRegister("dump_vars",    ConListDumpVariables);
    01510   IConsoleCmdRegister("echo",         ConEcho);
    01511   IConsoleCmdRegister("echoc",        ConEchoC);
    01512   IConsoleCmdRegister("exec",         ConExec);
    01513   IConsoleCmdRegister("exit",         ConExit);
    01514   IConsoleCmdRegister("part",         ConPart);
    01515   IConsoleCmdRegister("help",         ConHelp);
    01516   IConsoleCmdRegister("info_cmd",     ConInfoCmd);
    01517   IConsoleCmdRegister("info_var",     ConInfoVar);
    01518   IConsoleCmdRegister("list_cmds",    ConListCommands);
    01519   IConsoleCmdRegister("list_vars",    ConListVariables);
    01520   IConsoleCmdRegister("list_aliases", ConListAliases);
    01521   IConsoleCmdRegister("newgame",      ConNewGame);
    01522   IConsoleCmdRegister("restart",      ConRestart);
    01523   IConsoleCmdRegister("getseed",      ConGetSeed);
    01524   IConsoleCmdRegister("getdate",      ConGetDate);
    01525   IConsoleCmdRegister("quit",         ConExit);
    01526   IConsoleCmdRegister("resetengines", ConResetEngines);
    01527   IConsoleCmdRegister("return",       ConReturn);
    01528   IConsoleCmdRegister("screenshot",   ConScreenShot);
    01529   IConsoleCmdRegister("script",       ConScript);
    01530   IConsoleCmdRegister("scrollto",     ConScrollToTile);
    01531   IConsoleCmdRegister("alias",        ConAlias);
    01532   IConsoleCmdRegister("load",         ConLoad);
    01533   IConsoleCmdRegister("rm",           ConRemove);
    01534   IConsoleCmdRegister("save",         ConSave);
    01535   IConsoleCmdRegister("saveconfig",   ConSaveConfig);
    01536   IConsoleCmdRegister("ls",           ConListFiles);
    01537   IConsoleCmdRegister("cd",           ConChangeDirectory);
    01538   IConsoleCmdRegister("pwd",          ConPrintWorkingDirectory);
    01539   IConsoleCmdRegister("clear",        ConClearBuffer);
    01540   IConsoleCmdRegister("patch",        ConPatch);
    01541   IConsoleCmdRegister("list_patches", ConListPatches);
    01542
    01543   IConsoleAliasRegister("dir",      "ls");
    01544   IConsoleAliasRegister("del",      "rm %+");
    01545   IConsoleAliasRegister("newmap",   "newgame");
    01546   IConsoleAliasRegister("new_map",  "newgame");
    01547   IConsoleAliasRegister("new_game", "newgame");
    01548
    01549
    01550   IConsoleVarRegister("developer", &_stdlib_developer, ICONSOLE_VAR_BYTE, "Redirect debugging output from the console/command line to the ingame console (value 2). Default value: 1");
    01551
    01552   /* networking variables and functions */
    01553 #ifdef ENABLE_NETWORK
    01554   /* Network hooks; only active in network */
    01555   IConsoleCmdHookAdd ("resetengines", ICONSOLE_HOOK_ACCESS, ConHookNoNetwork);
    01556
    01557   /*** Networking commands ***/
    01558   IConsoleCmdRegister("say",             ConSay);
    01559   IConsoleCmdHookAdd("say",              ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01560   IConsoleCmdRegister("players",             ConPlayers);
    01561   IConsoleCmdHookAdd("players",              ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01562   IConsoleCmdRegister("say_player",      ConSayPlayer);
    01563   IConsoleCmdHookAdd("say_player",       ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01564   IConsoleCmdRegister("say_client",      ConSayClient);
    01565   IConsoleCmdHookAdd("say_client",       ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01566
    01567   IConsoleCmdRegister("connect",         ConNetworkConnect);
    01568   IConsoleCmdHookAdd("connect",          ICONSOLE_HOOK_ACCESS, ConHookClientOnly);
    01569   IConsoleAliasRegister("join",          "connect %A");
    01570   IConsoleCmdRegister("clients",         ConNetworkClients);
    01571   IConsoleCmdHookAdd("clients",          ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01572   IConsoleCmdRegister("status",          ConStatus);
    01573   IConsoleCmdHookAdd("status",           ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01574   IConsoleCmdRegister("server_info",     ConServerInfo);
    01575   IConsoleCmdHookAdd("server_info",      ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01576   IConsoleAliasRegister("info",          "server_info");
    01577   IConsoleCmdRegister("rcon",            ConRcon);
    01578   IConsoleCmdHookAdd("rcon",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01579
    01580   IConsoleCmdRegister("reset_company",   ConResetCompany);
    01581   IConsoleCmdHookAdd("reset_company",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01582   IConsoleAliasRegister("clean_company", "reset_company %A");
    01583   IConsoleCmdRegister("kick",            ConKick);
    01584   IConsoleCmdHookAdd("kick",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01585   IConsoleCmdRegister("ban",             ConBan);
    01586   IConsoleCmdHookAdd("ban",              ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01587   IConsoleCmdRegister("unban",           ConUnBan);
    01588   IConsoleCmdHookAdd("unban",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01589   IConsoleCmdRegister("banlist",         ConBanList);
    01590   IConsoleCmdHookAdd("banlist",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01591
    01592   IConsoleCmdRegister("pause",           ConPauseGame);
    01593   IConsoleCmdHookAdd("pause",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01594   IConsoleCmdRegister("unpause",         ConUnPauseGame);
    01595   IConsoleCmdHookAdd("unpause",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01596
    01597   /*** Networking variables ***/
    01598   IConsoleVarRegister("net_frame_freq",        &_network_frame_freq, ICONSOLE_VAR_BYTE, "The amount of frames before a command will be (visibly) executed. Default value: 1");
    01599   IConsoleVarHookAdd("net_frame_freq",         ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01600   IConsoleVarRegister("net_sync_freq",         &_network_sync_freq,  ICONSOLE_VAR_UINT16, "The amount of frames to check if the game is still in sync. Default value: 100");
    01601   IConsoleVarHookAdd("net_sync_freq",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01602
    01603   IConsoleVarStringRegister("server_pw",       &_network_server_password, sizeof(_network_server_password), "Set the server password to protect your server. Use '*' to clear the password");
    01604   IConsoleVarHookAdd("server_pw",              ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01605   IConsoleVarHookAdd("server_pw",              ICONSOLE_HOOK_POST_ACTION, ConHookServerPW);
    01606   IConsoleAliasRegister("server_password",     "server_pw %+");
    01607   IConsoleVarStringRegister("rcon_pw",         &_network_rcon_password, sizeof(_network_rcon_password), "Set the rcon-password to change server behaviour. Use '*' to disable rcon");
    01608   IConsoleVarHookAdd("rcon_pw",                ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01609   IConsoleVarHookAdd("rcon_pw",                ICONSOLE_HOOK_POST_ACTION, ConHookRconPW);
    01610   IConsoleAliasRegister("rcon_password",       "rcon_pw %+");
    01611   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");
    01612   IConsoleVarHookAdd("company_pw",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01613   IConsoleVarProcAdd("company_pw",             NetworkChangeCompanyPassword);
    01614   IConsoleAliasRegister("company_password",    "company_pw %+");
    01615
    01616   IConsoleVarStringRegister("name",            &_network_player_name, sizeof(_network_player_name), "Set your name for multiplayer");
    01617   IConsoleVarHookAdd("name",                   ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
    01618   IConsoleVarHookAdd("name",                   ICONSOLE_HOOK_POST_ACTION, ConProcPlayerName);
    01619   IConsoleVarStringRegister("server_name",     &_network_server_name, sizeof(_network_server_name), "Set the name of the server for multiplayer");
    01620   IConsoleVarHookAdd("server_name",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01621   IConsoleVarHookAdd("server_name",            ICONSOLE_HOOK_POST_ACTION, ConHookServerName);
    01622
    01623   IConsoleVarRegister("server_port",           &_network_server_port, ICONSOLE_VAR_UINT32, "Set the server port. Changes take effect the next time you start a server");
    01624   IConsoleVarRegister("server_ip",             &_network_server_bind_ip, ICONSOLE_VAR_UINT32, "Set the IP the server binds to. Changes take effect the next time you start a server. Use 'all' to bind to any IP.");
    01625   IConsoleVarProcAdd("server_ip",              ConProcServerIP);
    01626   IConsoleAliasRegister("server_bind_ip",      "server_ip %+");
    01627   IConsoleAliasRegister("server_ip_bind",      "server_ip %+");
    01628   IConsoleAliasRegister("server_bind",         "server_ip %+");
    01629   IConsoleVarRegister("server_advertise",      &_network_advertise, ICONSOLE_VAR_BOOLEAN, "Set if the server will advertise to the master server and show up there");
    01630   IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01631   IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_POST_ACTION, ConHookServerAdvertise);
    01632
    01633   IConsoleVarRegister("max_clients",           &_network_game_info.clients_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of connected players during runtime. Default value: 10");
    01634   IConsoleVarHookAdd("max_clients",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01635   IConsoleVarHookAdd("max_clients",            ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxClientsCount);
    01636   IConsoleVarRegister("max_companies",         &_network_game_info.companies_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active companies during runtime. Default value: 8");
    01637   IConsoleVarHookAdd("max_companies",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01638   IConsoleVarHookAdd("max_companies",          ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxCompaniesCount);
    01639   IConsoleVarRegister("max_spectators",        &_network_game_info.spectators_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active spectators during runtime. Default value: 9");
    01640   IConsoleVarHookAdd("max_spectators",         ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01641   IConsoleVarHookAdd("max_spectators",         ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxSpectatorsCount);
    01642
    01643   IConsoleVarRegister("max_join_time",         &_network_max_join_time, ICONSOLE_VAR_UINT16, "Set the maximum amount of time (ticks) a client is allowed to join. Default value: 500");
    01644
    01645   IConsoleVarRegister("pause_on_join",         &_network_pause_on_join, ICONSOLE_VAR_BOOLEAN, "Set if the server should pause gameplay while a client is joining. This might help slow users");
    01646   IConsoleVarHookAdd("pause_on_join",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01647
    01648   IConsoleVarRegister("autoclean_companies",   &_network_autoclean_companies, ICONSOLE_VAR_BOOLEAN, "Automatically shut down inactive companies to free them up for other players. Customize with 'autoclean_(un)protected'");
    01649   IConsoleVarHookAdd("autoclean_companies",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01650   IConsoleVarRegister("autoclean_protected",   &_network_autoclean_protected, ICONSOLE_VAR_BYTE, "Automatically remove the password from an inactive company after the given amount of months");
    01651   IConsoleVarHookAdd("autoclean_protected",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01652   IConsoleVarRegister("autoclean_unprotected", &_network_autoclean_unprotected, ICONSOLE_VAR_BYTE, "Automatically shut down inactive companies after the given amount of months");
    01653   IConsoleVarHookAdd("autoclean_unprotected",  ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01654   IConsoleVarRegister("restart_game_year",     &_network_restart_game_year, ICONSOLE_VAR_UINT16, "Auto-restart the server when Jan 1st of the set year is reached. Use '0' to disable this");
    01655   IConsoleVarHookAdd("restart_game_year",      ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01656
    01657   IConsoleVarRegister("min_players",           &_network_min_players, ICONSOLE_VAR_BYTE, "Automatically pause the game when the number of active players passes below the given amount");
    01658   IConsoleVarHookAdd("min_players",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01659   IConsoleVarHookAdd("min_players",            ICONSOLE_HOOK_POST_ACTION, ConHookCheckMinPlayers);
    01660   IConsoleVarRegister("reload_cfg",            &_network_reload_cfg, ICONSOLE_VAR_BOOLEAN, "reload the entire config file between the end of this game, and starting the next new game - dedicated servers");
    01661   IConsoleVarHookAdd("reload_cfg",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
    01662
    01663 #endif /* ENABLE_NETWORK */
    01664
    01665   // debugging stuff
    01666 #ifdef _DEBUG
    01667   IConsoleDebugLibRegister();
    01668 #endif
    01669 }