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 }

Generated on Wed Oct 1 17:03:20 2008 for openttd by  doxygen 1.5.6