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