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