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