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