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