00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "console_internal.h"
00008 #include "debug.h"
00009 #include "engine_func.h"
00010 #include "landscape.h"
00011 #include "saveload/saveload.h"
00012 #include "variables.h"
00013 #include "network/network.h"
00014 #include "network/network_func.h"
00015 #include "network/network_base.h"
00016 #include "command_func.h"
00017 #include "settings_func.h"
00018 #include "fios.h"
00019 #include "fileio_func.h"
00020 #include "screenshot.h"
00021 #include "genworld.h"
00022 #include "strings_func.h"
00023 #include "viewport_func.h"
00024 #include "window_func.h"
00025 #include "functions.h"
00026 #include "map_func.h"
00027 #include "date_func.h"
00028 #include "vehicle_func.h"
00029 #include "string_func.h"
00030 #include "company_func.h"
00031 #include "company_base.h"
00032 #include "settings_type.h"
00033 #include "gamelog.h"
00034
00035 #ifdef ENABLE_NETWORK
00036 #include "table/strings.h"
00037 #endif
00038
00039
00040 static FILE *_script_file;
00041 static bool _script_running;
00042
00043
00044 #define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
00045 #define DEF_CONSOLE_HOOK(function) static bool function()
00046
00047
00048
00049
00050
00051
00052 #ifdef ENABLE_NETWORK
00053
00054 static inline bool NetworkAvailable()
00055 {
00056 if (!_network_available) {
00057 IConsoleError("You cannot use this command because there is no network available.");
00058 return false;
00059 }
00060 return true;
00061 }
00062
00063 DEF_CONSOLE_HOOK(ConHookServerOnly)
00064 {
00065 if (!NetworkAvailable()) return false;
00066
00067 if (!_network_server) {
00068 IConsoleError("This command/variable is only available to a network server.");
00069 return false;
00070 }
00071 return true;
00072 }
00073
00074 DEF_CONSOLE_HOOK(ConHookClientOnly)
00075 {
00076 if (!NetworkAvailable()) return false;
00077
00078 if (_network_server) {
00079 IConsoleError("This command/variable is not available to a network server.");
00080 return false;
00081 }
00082 return true;
00083 }
00084
00085 DEF_CONSOLE_HOOK(ConHookNeedNetwork)
00086 {
00087 if (!NetworkAvailable()) return false;
00088
00089 if (!_networking) {
00090 IConsoleError("Not connected. This command/variable is only available in multiplayer.");
00091 return false;
00092 }
00093 return true;
00094 }
00095
00096 DEF_CONSOLE_HOOK(ConHookNoNetwork)
00097 {
00098 if (_networking) {
00099 IConsoleError("This command/variable is forbidden in multiplayer.");
00100 return false;
00101 }
00102 return true;
00103 }
00104
00105 #endif
00106
00107 static void IConsoleHelp(const char *str)
00108 {
00109 IConsolePrintF(CC_WARNING, "- %s", str);
00110 }
00111
00112 DEF_CONSOLE_CMD(ConResetEngines)
00113 {
00114 if (argc == 0) {
00115 IConsoleHelp("Reset status data of all engines. This might solve some issues with 'lost' engines. Usage: 'resetengines'");
00116 return true;
00117 }
00118
00119 StartupEngines();
00120 return true;
00121 }
00122
00123 #ifdef _DEBUG
00124 DEF_CONSOLE_CMD(ConResetTile)
00125 {
00126 if (argc == 0) {
00127 IConsoleHelp("Reset a tile to bare land. Usage: 'resettile <tile>'");
00128 IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
00129 return true;
00130 }
00131
00132 if (argc == 2) {
00133 uint32 result;
00134 if (GetArgumentInteger(&result, argv[1])) {
00135 DoClearSquare((TileIndex)result);
00136 return true;
00137 }
00138 }
00139
00140 return false;
00141 }
00142
00143 DEF_CONSOLE_CMD(ConStopAllVehicles)
00144 {
00145 if (argc == 0) {
00146 IConsoleHelp("Stops all vehicles in the game. For debugging only! Use at your own risk... Usage: 'stopall'");
00147 return true;
00148 }
00149
00150 StopAllVehicles();
00151 return true;
00152 }
00153 #endif
00154
00155 DEF_CONSOLE_CMD(ConScrollToTile)
00156 {
00157 if (argc == 0) {
00158 IConsoleHelp("Center the screen on a given tile. Usage: 'scrollto <tile>'");
00159 IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
00160 return true;
00161 }
00162
00163 if (argc == 2) {
00164 uint32 result;
00165 if (GetArgumentInteger(&result, argv[1])) {
00166 if (result >= MapSize()) {
00167 IConsolePrint(CC_ERROR, "Tile does not exist");
00168 return true;
00169 }
00170 ScrollMainWindowToTile((TileIndex)result);
00171 return true;
00172 }
00173 }
00174
00175 return false;
00176 }
00177
00178 extern void BuildFileList();
00179 extern void SetFiosType(const byte fiostype);
00180
00181
00182 DEF_CONSOLE_CMD(ConSave)
00183 {
00184 if (argc == 0) {
00185 IConsoleHelp("Save the current game. Usage: 'save <filename>'");
00186 return true;
00187 }
00188
00189 if (argc == 2) {
00190 char *filename = str_fmt("%s.sav", argv[1]);
00191 IConsolePrint(CC_DEFAULT, "Saving map...");
00192
00193 if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
00194 IConsolePrint(CC_ERROR, "Saving map failed");
00195 } else {
00196 IConsolePrintF(CC_DEFAULT, "Map sucessfully saved to %s", filename);
00197 }
00198 free(filename);
00199 return true;
00200 }
00201
00202 return false;
00203 }
00204
00205
00206 DEF_CONSOLE_CMD(ConSaveConfig)
00207 {
00208 if (argc == 0) {
00209 IConsoleHelp("Saves the current config, typically to 'openttd.cfg'.");
00210 return true;
00211 }
00212
00213 SaveToConfig();
00214 IConsolePrint(CC_DEFAULT, "Saved config.");
00215 return true;
00216 }
00217
00218 static const FiosItem* GetFiosItem(const char* file)
00219 {
00220 _saveload_mode = SLD_LOAD_GAME;
00221 BuildFileList();
00222
00223 for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
00224 if (strcmp(file, item->name) == 0) return item;
00225 if (strcmp(file, item->title) == 0) return item;
00226 }
00227
00228
00229 char *endptr;
00230 int i = strtol(file, &endptr, 10);
00231 if (file == endptr || *endptr != '\0') i = -1;
00232
00233 return IsInsideMM(i, 0, _fios_items.Length()) ? _fios_items.Get(i) : NULL;
00234 }
00235
00236
00237 DEF_CONSOLE_CMD(ConLoad)
00238 {
00239 if (argc == 0) {
00240 IConsoleHelp("Load a game by name or index. Usage: 'load <file | number>'");
00241 return true;
00242 }
00243
00244 if (argc != 2) return false;
00245
00246 const char *file = argv[1];
00247 const FiosItem *item = GetFiosItem(file);
00248 if (item != NULL) {
00249 switch (item->type) {
00250 case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: {
00251 _switch_mode = SM_LOAD;
00252 SetFiosType(item->type);
00253
00254 strecpy(_file_to_saveload.name, FiosBrowseTo(item), lastof(_file_to_saveload.name));
00255 strecpy(_file_to_saveload.title, item->title, lastof(_file_to_saveload.title));
00256 } break;
00257 default: IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
00258 }
00259 } else {
00260 IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
00261 }
00262
00263 FiosFreeSavegameList();
00264 return true;
00265 }
00266
00267
00268 DEF_CONSOLE_CMD(ConRemove)
00269 {
00270 if (argc == 0) {
00271 IConsoleHelp("Remove a savegame by name or index. Usage: 'rm <file | number>'");
00272 return true;
00273 }
00274
00275 if (argc != 2) return false;
00276
00277 const char *file = argv[1];
00278 const FiosItem *item = GetFiosItem(file);
00279 if (item != NULL) {
00280 if (!FiosDelete(item->name))
00281 IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
00282 } else {
00283 IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
00284 }
00285
00286 FiosFreeSavegameList();
00287 return true;
00288 }
00289
00290
00291
00292 DEF_CONSOLE_CMD(ConListFiles)
00293 {
00294 if (argc == 0) {
00295 IConsoleHelp("List all loadable savegames and directories in the current dir via console. Usage: 'ls | dir'");
00296 return true;
00297 }
00298
00299 BuildFileList();
00300
00301 for (uint i = 0; i < _fios_items.Length(); i++) {
00302 IConsolePrintF(CC_DEFAULT, "%d) %s", i, _fios_items[i].title);
00303 }
00304
00305 FiosFreeSavegameList();
00306 return true;
00307 }
00308
00309
00310 DEF_CONSOLE_CMD(ConChangeDirectory)
00311 {
00312 if (argc == 0) {
00313 IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
00314 return true;
00315 }
00316
00317 if (argc != 2) return false;
00318
00319 const char *file = argv[1];
00320 const FiosItem *item = GetFiosItem(file);
00321 if (item != NULL) {
00322 switch (item->type) {
00323 case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
00324 FiosBrowseTo(item);
00325 break;
00326 default: IConsolePrintF(CC_ERROR, "%s: Not a directory.", file);
00327 }
00328 } else {
00329 IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
00330 }
00331
00332 FiosFreeSavegameList();
00333 return true;
00334 }
00335
00336 DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
00337 {
00338 const char *path;
00339
00340 if (argc == 0) {
00341 IConsoleHelp("Print out the current working directory. Usage: 'pwd'");
00342 return true;
00343 }
00344
00345
00346 FiosGetSavegameList(SLD_LOAD_GAME);
00347 FiosFreeSavegameList();
00348
00349 FiosGetDescText(&path, NULL);
00350 IConsolePrint(CC_DEFAULT, path);
00351 return true;
00352 }
00353
00354 DEF_CONSOLE_CMD(ConClearBuffer)
00355 {
00356 if (argc == 0) {
00357 IConsoleHelp("Clear the console buffer. Usage: 'clear'");
00358 return true;
00359 }
00360
00361 IConsoleClearBuffer();
00362 InvalidateWindow(WC_CONSOLE, 0);
00363 return true;
00364 }
00365
00366
00367
00368
00369
00370 #ifdef ENABLE_NETWORK
00371
00372 DEF_CONSOLE_CMD(ConBan)
00373 {
00374 NetworkClientInfo *ci;
00375 const char *banip = NULL;
00376 ClientID client_id;
00377
00378 if (argc == 0) {
00379 IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id>'");
00380 IConsoleHelp("For client-id's, see the command 'clients'");
00381 IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
00382 return true;
00383 }
00384
00385 if (argc != 2) return false;
00386
00387 if (strchr(argv[1], '.') == NULL) {
00388 client_id = (ClientID)atoi(argv[1]);
00389 ci = NetworkFindClientInfoFromClientID(client_id);
00390 } else {
00391 ci = NetworkFindClientInfoFromIP(argv[1]);
00392 if (ci == NULL) {
00393 banip = argv[1];
00394 client_id = (ClientID)-1;
00395 } else {
00396 client_id = ci->client_id;
00397 }
00398 }
00399
00400 if (client_id == CLIENT_ID_SERVER) {
00401 IConsoleError("Silly boy, you can not ban yourself!");
00402 return true;
00403 }
00404
00405 if (client_id == INVALID_CLIENT_ID || (ci == NULL && client_id != (ClientID)-1)) {
00406 IConsoleError("Invalid client");
00407 return true;
00408 }
00409
00410 if (ci != NULL) {
00411 IConsolePrint(CC_DEFAULT, "Client banned");
00412 banip = GetClientIP(ci);
00413 NetworkServerSendError(client_id, NETWORK_ERROR_KICKED);
00414 } else {
00415 IConsolePrint(CC_DEFAULT, "Client not online, banned IP");
00416 }
00417
00418
00419 for (uint index = 0; index < lengthof(_network_ban_list); index++) {
00420 if (_network_ban_list[index] == NULL) {
00421 _network_ban_list[index] = strdup(banip);
00422 break;
00423 }
00424 }
00425
00426 return true;
00427 }
00428
00429 DEF_CONSOLE_CMD(ConUnBan)
00430 {
00431 uint i, index;
00432
00433 if (argc == 0) {
00434 IConsoleHelp("Unban a client from a network game. Usage: 'unban <ip | client-id>'");
00435 IConsoleHelp("For a list of banned IP's, see the command 'banlist'");
00436 return true;
00437 }
00438
00439 if (argc != 2) return false;
00440
00441 index = (strchr(argv[1], '.') == NULL) ? atoi(argv[1]) : 0;
00442 index--;
00443
00444 for (i = 0; i < lengthof(_network_ban_list); i++) {
00445 if (_network_ban_list[i] == NULL) continue;
00446
00447 if (strcmp(_network_ban_list[i], argv[1]) == 0 || index == i) {
00448 free(_network_ban_list[i]);
00449 _network_ban_list[i] = NULL;
00450 IConsolePrint(CC_DEFAULT, "IP unbanned.");
00451 return true;
00452 }
00453 }
00454
00455 IConsolePrint(CC_DEFAULT, "IP not in ban-list.");
00456 return true;
00457 }
00458
00459 DEF_CONSOLE_CMD(ConBanList)
00460 {
00461 uint i;
00462
00463 if (argc == 0) {
00464 IConsoleHelp("List the IP's of banned clients: Usage 'banlist'");
00465 return true;
00466 }
00467
00468 IConsolePrint(CC_DEFAULT, "Banlist: ");
00469
00470 for (i = 0; i < lengthof(_network_ban_list); i++) {
00471 if (_network_ban_list[i] != NULL)
00472 IConsolePrintF(CC_DEFAULT, " %d) %s", i + 1, _network_ban_list[i]);
00473 }
00474
00475 return true;
00476 }
00477
00478 DEF_CONSOLE_CMD(ConPauseGame)
00479 {
00480 if (argc == 0) {
00481 IConsoleHelp("Pause a network game. Usage: 'pause'");
00482 return true;
00483 }
00484
00485 if (_pause_game == 0) {
00486 DoCommandP(0, 1, 0, CMD_PAUSE);
00487 IConsolePrint(CC_DEFAULT, "Game paused.");
00488 } else {
00489 IConsolePrint(CC_DEFAULT, "Game is already paused.");
00490 }
00491
00492 return true;
00493 }
00494
00495 DEF_CONSOLE_CMD(ConUnPauseGame)
00496 {
00497 if (argc == 0) {
00498 IConsoleHelp("Unpause a network game. Usage: 'unpause'");
00499 return true;
00500 }
00501
00502 if (_pause_game != 0) {
00503 DoCommandP(0, 0, 0, CMD_PAUSE);
00504 IConsolePrint(CC_DEFAULT, "Game unpaused.");
00505 } else {
00506 IConsolePrint(CC_DEFAULT, "Game is already unpaused.");
00507 }
00508
00509 return true;
00510 }
00511
00512 DEF_CONSOLE_CMD(ConRcon)
00513 {
00514 if (argc == 0) {
00515 IConsoleHelp("Remote control the server from another client. Usage: 'rcon <password> <command>'");
00516 IConsoleHelp("Remember to enclose the command in quotes, otherwise only the first parameter is sent");
00517 return true;
00518 }
00519
00520 if (argc < 3) return false;
00521
00522 if (_network_server) {
00523 IConsoleCmdExec(argv[2]);
00524 } else {
00525 NetworkClientSendRcon(argv[1], argv[2]);
00526 }
00527 return true;
00528 }
00529
00530 DEF_CONSOLE_CMD(ConStatus)
00531 {
00532 if (argc == 0) {
00533 IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
00534 return true;
00535 }
00536
00537 NetworkServerShowStatusToConsole();
00538 return true;
00539 }
00540
00541 DEF_CONSOLE_CMD(ConServerInfo)
00542 {
00543 if (argc == 0) {
00544 IConsoleHelp("List current and maximum client/company limits. Usage 'server_info'");
00545 IConsoleHelp("You can change these values by setting the variables 'max_clients', 'max_companies' and 'max_spectators'");
00546 return true;
00547 }
00548
00549 IConsolePrintF(CC_DEFAULT, "Current/maximum clients: %2d/%2d", _network_game_info.clients_on, _settings_client.network.max_clients);
00550 IConsolePrintF(CC_DEFAULT, "Current/maximum companies: %2d/%2d", ActiveCompanyCount(), _settings_client.network.max_companies);
00551 IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), _settings_client.network.max_spectators);
00552
00553 return true;
00554 }
00555
00556 DEF_CONSOLE_CMD(ConKick)
00557 {
00558 NetworkClientInfo *ci;
00559 ClientID client_id;
00560
00561 if (argc == 0) {
00562 IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id>'");
00563 IConsoleHelp("For client-id's, see the command 'clients'");
00564 return true;
00565 }
00566
00567 if (argc != 2) return false;
00568
00569 if (strchr(argv[1], '.') == NULL) {
00570 client_id = (ClientID)atoi(argv[1]);
00571 ci = NetworkFindClientInfoFromClientID(client_id);
00572 } else {
00573 ci = NetworkFindClientInfoFromIP(argv[1]);
00574 client_id = (ci == NULL) ? INVALID_CLIENT_ID : ci->client_id;
00575 }
00576
00577 if (client_id == CLIENT_ID_SERVER) {
00578 IConsoleError("Silly boy, you can not kick yourself!");
00579 return true;
00580 }
00581
00582 if (client_id == INVALID_CLIENT_ID) {
00583 IConsoleError("Invalid client");
00584 return true;
00585 }
00586
00587 if (ci != NULL) {
00588 NetworkServerSendError(client_id, NETWORK_ERROR_KICKED);
00589 } else {
00590 IConsoleError("Client not found");
00591 }
00592
00593 return true;
00594 }
00595
00596 DEF_CONSOLE_CMD(ConResetCompany)
00597 {
00598 CompanyID index;
00599
00600 if (argc == 0) {
00601 IConsoleHelp("Remove an idle company from the game. Usage: 'reset_company <company-id>'");
00602 IConsoleHelp("For company-id's, see the list of companies from the dropdown menu. Company 1 is 1, etc.");
00603 return true;
00604 }
00605
00606 if (argc != 2) return false;
00607
00608 index = (CompanyID)(atoi(argv[1]) - 1);
00609
00610
00611 if (!IsValidCompanyID(index)) {
00612 IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_COMPANIES);
00613 return true;
00614 }
00615
00616 const Company *c = GetCompany(index);
00617
00618 if (c->is_ai) {
00619 IConsoleError("Company is owned by an AI.");
00620 return true;
00621 }
00622
00623 if (NetworkCompanyHasClients(index)) {
00624 IConsoleError("Cannot remove company: a client is connected to that company.");
00625 return false;
00626 }
00627 const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER);
00628 if (ci->client_playas == index) {
00629 IConsoleError("Cannot remove company: the server is connected to that company.");
00630 return true;
00631 }
00632
00633
00634 DoCommandP(0, 2, index, CMD_COMPANY_CTRL);
00635 IConsolePrint(CC_DEFAULT, "Company deleted.");
00636
00637 return true;
00638 }
00639
00640 DEF_CONSOLE_CMD(ConNetworkClients)
00641 {
00642 if (argc == 0) {
00643 IConsoleHelp("Get a list of connected clients including their ID, name, company-id, and IP. Usage: 'clients'");
00644 return true;
00645 }
00646
00647 NetworkPrintClients();
00648
00649 return true;
00650 }
00651
00652 DEF_CONSOLE_CMD(ConNetworkConnect)
00653 {
00654 char *ip;
00655 const char *port = NULL;
00656 const char *company = NULL;
00657 uint16 rport;
00658
00659 if (argc == 0) {
00660 IConsoleHelp("Connect to a remote OTTD server and join the game. Usage: 'connect <ip>'");
00661 IConsoleHelp("IP can contain port and company: 'IP[[#Company]:Port]', eg: 'server.ottd.org#2:443'");
00662 IConsoleHelp("Company #255 is spectator all others are a certain company with Company 1 being #1");
00663 return true;
00664 }
00665
00666 if (argc < 2) return false;
00667 if (_networking) NetworkDisconnect();
00668
00669 ip = argv[1];
00670
00671 rport = NETWORK_DEFAULT_PORT;
00672 _network_playas = COMPANY_NEW_COMPANY;
00673
00674 ParseConnectionString(&company, &port, ip);
00675
00676 IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip);
00677 if (company != NULL) {
00678 _network_playas = (CompanyID)atoi(company);
00679 IConsolePrintF(CC_DEFAULT, " company-no: %d", _network_playas);
00680
00681
00682
00683 if (_network_playas != COMPANY_SPECTATOR) {
00684 _network_playas--;
00685 if (!IsValidCompanyID(_network_playas)) return false;
00686 }
00687 }
00688 if (port != NULL) {
00689 rport = atoi(port);
00690 IConsolePrintF(CC_DEFAULT, " port: %s", port);
00691 }
00692
00693 NetworkClientConnectGame(ip, rport);
00694
00695 return true;
00696 }
00697
00698 #endif
00699
00700
00701
00702
00703
00704 DEF_CONSOLE_CMD(ConExec)
00705 {
00706 char cmdline[ICON_CMDLN_SIZE];
00707 char *cmdptr;
00708
00709 if (argc == 0) {
00710 IConsoleHelp("Execute a local script file. Usage: 'exec <script> <?>'");
00711 return true;
00712 }
00713
00714 if (argc < 2) return false;
00715
00716 _script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
00717
00718 if (_script_file == NULL) {
00719 if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
00720 return true;
00721 }
00722
00723 _script_running = true;
00724
00725 while (_script_running && fgets(cmdline, sizeof(cmdline), _script_file) != NULL) {
00726
00727 for (cmdptr = cmdline; *cmdptr != '\0'; cmdptr++) {
00728 if (*cmdptr == '\n' || *cmdptr == '\r') {
00729 *cmdptr = '\0';
00730 break;
00731 }
00732 }
00733 IConsoleCmdExec(cmdline);
00734 }
00735
00736 if (ferror(_script_file))
00737 IConsoleError("Encountered errror while trying to read from script file");
00738
00739 _script_running = false;
00740 FioFCloseFile(_script_file);
00741 return true;
00742 }
00743
00744 DEF_CONSOLE_CMD(ConReturn)
00745 {
00746 if (argc == 0) {
00747 IConsoleHelp("Stop executing a running script. Usage: 'return'");
00748 return true;
00749 }
00750
00751 _script_running = false;
00752 return true;
00753 }
00754
00755
00756
00757
00758 extern bool CloseConsoleLogIfActive();
00759
00760 DEF_CONSOLE_CMD(ConScript)
00761 {
00762 extern FILE* _iconsole_output_file;
00763
00764 if (argc == 0) {
00765 IConsoleHelp("Start or stop logging console output to a file. Usage: 'script <filename>'");
00766 IConsoleHelp("If filename is omitted, a running log is stopped if it is active");
00767 return true;
00768 }
00769
00770 if (!CloseConsoleLogIfActive()) {
00771 if (argc < 2) return false;
00772
00773 IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]);
00774 _iconsole_output_file = fopen(argv[1], "ab");
00775 if (_iconsole_output_file == NULL) IConsoleError("could not open file");
00776 }
00777
00778 return true;
00779 }
00780
00781
00782 DEF_CONSOLE_CMD(ConEcho)
00783 {
00784 if (argc == 0) {
00785 IConsoleHelp("Print back the first argument to the console. Usage: 'echo <arg>'");
00786 return true;
00787 }
00788
00789 if (argc < 2) return false;
00790 IConsolePrint(CC_DEFAULT, argv[1]);
00791 return true;
00792 }
00793
00794 DEF_CONSOLE_CMD(ConEchoC)
00795 {
00796 if (argc == 0) {
00797 IConsoleHelp("Print back the first argument to the console in a given colour. Usage: 'echoc <colour> <arg2>'");
00798 return true;
00799 }
00800
00801 if (argc < 3) return false;
00802 IConsolePrint((ConsoleColour)atoi(argv[1]), argv[2]);
00803 return true;
00804 }
00805
00806 DEF_CONSOLE_CMD(ConNewGame)
00807 {
00808 if (argc == 0) {
00809 IConsoleHelp("Start a new game. Usage: 'newgame [seed]'");
00810 IConsoleHelp("The server can force a new game using 'newgame'; any client joined will rejoin after the server is done generating the new game.");
00811 return true;
00812 }
00813
00814 StartNewGameWithoutGUI((argc == 2) ? (uint)atoi(argv[1]) : GENERATE_NEW_SEED);
00815 return true;
00816 }
00817
00818 extern void SwitchMode(int new_mode);
00819
00820 DEF_CONSOLE_CMD(ConRestart)
00821 {
00822 if (argc == 0) {
00823 IConsoleHelp("Restart game. Usage: 'restart'");
00824 IConsoleHelp("Restarts a game. It tries to reproduce the exact same map as the game started with.");
00825 return true;
00826 }
00827
00828
00829 _settings_game.game_creation.map_x = MapLogX();
00830 _settings_game.game_creation.map_y = FindFirstBit(MapSizeY());
00831 SwitchMode(SM_NEWGAME);
00832 return true;
00833 }
00834
00835 DEF_CONSOLE_CMD(ConGetSeed)
00836 {
00837 if (argc == 0) {
00838 IConsoleHelp("Returns the seed used to create this game. Usage: 'getseed'");
00839 IConsoleHelp("The seed can be used to reproduce the exact same map as the game started with.");
00840 return true;
00841 }
00842
00843 IConsolePrintF(CC_DEFAULT, "Generation Seed: %u", _settings_game.game_creation.generation_seed);
00844 return true;
00845 }
00846
00847 DEF_CONSOLE_CMD(ConGetDate)
00848 {
00849 if (argc == 0) {
00850 IConsoleHelp("Returns the current date (day-month-year) of the game. Usage: 'getdate'");
00851 return true;
00852 }
00853
00854 YearMonthDay ymd;
00855 ConvertDateToYMD(_date, &ymd);
00856 IConsolePrintF(CC_DEFAULT, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
00857 return true;
00858 }
00859
00860
00861 DEF_CONSOLE_CMD(ConAlias)
00862 {
00863 IConsoleAlias *alias;
00864
00865 if (argc == 0) {
00866 IConsoleHelp("Add a new alias, or redefine the behaviour of an existing alias . Usage: 'alias <name> <command>'");
00867 return true;
00868 }
00869
00870 if (argc < 3) return false;
00871
00872 alias = IConsoleAliasGet(argv[1]);
00873 if (alias == NULL) {
00874 IConsoleAliasRegister(argv[1], argv[2]);
00875 } else {
00876 free(alias->cmdline);
00877 alias->cmdline = strdup(argv[2]);
00878 }
00879 return true;
00880 }
00881
00882 DEF_CONSOLE_CMD(ConScreenShot)
00883 {
00884 if (argc == 0) {
00885 IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | no_con]'");
00886 IConsoleHelp("'big' makes a screenshot of the whole map, 'no_con' hides the console to create the screenshot");
00887 return true;
00888 }
00889
00890 if (argc > 3) return false;
00891
00892 SetScreenshotType(SC_VIEWPORT);
00893 if (argc > 1) {
00894 if (strcmp(argv[1], "big") == 0 || (argc == 3 && strcmp(argv[2], "big") == 0))
00895 SetScreenshotType(SC_WORLD);
00896
00897 if (strcmp(argv[1], "no_con") == 0 || (argc == 3 && strcmp(argv[2], "no_con") == 0))
00898 IConsoleClose();
00899 }
00900
00901 return true;
00902 }
00903
00904 DEF_CONSOLE_CMD(ConInfoVar)
00905 {
00906 static const char *_icon_vartypes[] = {"boolean", "byte", "uint16", "uint32", "int16", "int32", "string"};
00907 const IConsoleVar *var;
00908
00909 if (argc == 0) {
00910 IConsoleHelp("Print out debugging information about a variable. Usage: 'info_var <var>'");
00911 return true;
00912 }
00913
00914 if (argc < 2) return false;
00915
00916 var = IConsoleVarGet(argv[1]);
00917 if (var == NULL) {
00918 IConsoleError("the given variable was not found");
00919 return true;
00920 }
00921
00922 IConsolePrintF(CC_DEFAULT, "variable name: %s", var->name);
00923 IConsolePrintF(CC_DEFAULT, "variable type: %s", _icon_vartypes[var->type]);
00924 IConsolePrintF(CC_DEFAULT, "variable addr: 0x%X", var->addr);
00925
00926 if (var->hook.access) IConsoleWarning("variable is access hooked");
00927 if (var->hook.pre) IConsoleWarning("variable is pre hooked");
00928 if (var->hook.post) IConsoleWarning("variable is post hooked");
00929 return true;
00930 }
00931
00932
00933 DEF_CONSOLE_CMD(ConInfoCmd)
00934 {
00935 const IConsoleCmd *cmd;
00936
00937 if (argc == 0) {
00938 IConsoleHelp("Print out debugging information about a command. Usage: 'info_cmd <cmd>'");
00939 return true;
00940 }
00941
00942 if (argc < 2) return false;
00943
00944 cmd = IConsoleCmdGet(argv[1]);
00945 if (cmd == NULL) {
00946 IConsoleError("the given command was not found");
00947 return true;
00948 }
00949
00950 IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name);
00951 IConsolePrintF(CC_DEFAULT, "command proc: 0x%X", cmd->proc);
00952
00953 if (cmd->hook.access) IConsoleWarning("command is access hooked");
00954 if (cmd->hook.pre) IConsoleWarning("command is pre hooked");
00955 if (cmd->hook.post) IConsoleWarning("command is post hooked");
00956
00957 return true;
00958 }
00959
00960 DEF_CONSOLE_CMD(ConDebugLevel)
00961 {
00962 if (argc == 0) {
00963 IConsoleHelp("Get/set the default debugging level for the game. Usage: 'debug_level [<level>]'");
00964 IConsoleHelp("Level can be any combination of names, levels. Eg 'net=5 ms=4'. Remember to enclose it in \"'s");
00965 return true;
00966 }
00967
00968 if (argc > 2) return false;
00969
00970 if (argc == 1) {
00971 IConsolePrintF(CC_DEFAULT, "Current debug-level: '%s'", GetDebugString());
00972 } else {
00973 SetDebugString(argv[1]);
00974 }
00975
00976 return true;
00977 }
00978
00979 DEF_CONSOLE_CMD(ConExit)
00980 {
00981 if (argc == 0) {
00982 IConsoleHelp("Exit the game. Usage: 'exit'");
00983 return true;
00984 }
00985
00986 if (_game_mode == GM_NORMAL && _settings_client.gui.autosave_on_exit) DoExitSave();
00987
00988 _exit_game = true;
00989 return true;
00990 }
00991
00992 DEF_CONSOLE_CMD(ConPart)
00993 {
00994 if (argc == 0) {
00995 IConsoleHelp("Leave the currently joined/running game (only ingame). Usage: 'part'");
00996 return true;
00997 }
00998
00999 if (_game_mode != GM_NORMAL) return false;
01000
01001 _switch_mode = SM_MENU;
01002 return true;
01003 }
01004
01005 DEF_CONSOLE_CMD(ConHelp)
01006 {
01007 if (argc == 2) {
01008 const IConsoleCmd *cmd;
01009 const IConsoleVar *var;
01010 const IConsoleAlias *alias;
01011
01012 cmd = IConsoleCmdGet(argv[1]);
01013 if (cmd != NULL) {
01014 cmd->proc(0, NULL);
01015 return true;
01016 }
01017
01018 alias = IConsoleAliasGet(argv[1]);
01019 if (alias != NULL) {
01020 cmd = IConsoleCmdGet(alias->cmdline);
01021 if (cmd != NULL) {
01022 cmd->proc(0, NULL);
01023 return true;
01024 }
01025 IConsolePrintF(CC_ERROR, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline);
01026 return true;
01027 }
01028
01029 var = IConsoleVarGet(argv[1]);
01030 if (var != NULL && var->help != NULL) {
01031 IConsoleHelp(var->help);
01032 return true;
01033 }
01034
01035 IConsoleError("command or variable not found");
01036 return true;
01037 }
01038
01039 IConsolePrint(CC_WARNING, " ---- OpenTTD Console Help ---- ");
01040 IConsolePrint(CC_DEFAULT, " - variables: [command to list all variables: list_vars]");
01041 IConsolePrint(CC_DEFAULT, " set value with '<var> = <value>', use '++/--' to in-or decrement");
01042 IConsolePrint(CC_DEFAULT, " or omit '=' and just '<var> <value>'. get value with typing '<var>'");
01043 IConsolePrint(CC_DEFAULT, " - commands: [command to list all commands: list_cmds]");
01044 IConsolePrint(CC_DEFAULT, " call commands with '<command> <arg2> <arg3>...'");
01045 IConsolePrint(CC_DEFAULT, " - to assign strings, or use them as arguments, enclose it within quotes");
01046 IConsolePrint(CC_DEFAULT, " like this: '<command> \"string argument with spaces\"'");
01047 IConsolePrint(CC_DEFAULT, " - use 'help <command> | <variable>' to get specific information");
01048 IConsolePrint(CC_DEFAULT, " - scroll console output with shift + (up | down) | (pageup | pagedown))");
01049 IConsolePrint(CC_DEFAULT, " - scroll console input history with the up | down arrows");
01050 IConsolePrint(CC_DEFAULT, "");
01051 return true;
01052 }
01053
01054 DEF_CONSOLE_CMD(ConListCommands)
01055 {
01056 const IConsoleCmd *cmd;
01057 size_t l = 0;
01058
01059 if (argc == 0) {
01060 IConsoleHelp("List all registered commands. Usage: 'list_cmds [<pre-filter>]'");
01061 return true;
01062 }
01063
01064 if (argv[1] != NULL) l = strlen(argv[1]);
01065
01066 for (cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) {
01067 if (argv[1] == NULL || strncmp(cmd->name, argv[1], l) == 0) {
01068 IConsolePrintF(CC_DEFAULT, "%s", cmd->name);
01069 }
01070 }
01071
01072 return true;
01073 }
01074
01075 DEF_CONSOLE_CMD(ConListVariables)
01076 {
01077 const IConsoleVar *var;
01078 size_t l = 0;
01079
01080 if (argc == 0) {
01081 IConsoleHelp("List all registered variables. Usage: 'list_vars [<pre-filter>]'");
01082 return true;
01083 }
01084
01085 if (argv[1] != NULL) l = strlen(argv[1]);
01086
01087 for (var = _iconsole_vars; var != NULL; var = var->next) {
01088 if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0)
01089 IConsolePrintF(CC_DEFAULT, "%s", var->name);
01090 }
01091
01092 return true;
01093 }
01094
01095 DEF_CONSOLE_CMD(ConListAliases)
01096 {
01097 const IConsoleAlias *alias;
01098 size_t l = 0;
01099
01100 if (argc == 0) {
01101 IConsoleHelp("List all registered aliases. Usage: 'list_aliases [<pre-filter>]'");
01102 return true;
01103 }
01104
01105 if (argv[1] != NULL) l = strlen(argv[1]);
01106
01107 for (alias = _iconsole_aliases; alias != NULL; alias = alias->next) {
01108 if (argv[1] == NULL || strncmp(alias->name, argv[1], l) == 0)
01109 IConsolePrintF(CC_DEFAULT, "%s => %s", alias->name, alias->cmdline);
01110 }
01111
01112 return true;
01113 }
01114
01115 #ifdef ENABLE_NETWORK
01116
01117 DEF_CONSOLE_CMD(ConSay)
01118 {
01119 if (argc == 0) {
01120 IConsoleHelp("Chat to your fellow players in a multiplayer game. Usage: 'say \"<msg>\"'");
01121 return true;
01122 }
01123
01124 if (argc != 2) return false;
01125
01126 if (!_network_server) {
01127 NetworkClientSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 , argv[1]);
01128 } else {
01129 NetworkServerSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], CLIENT_ID_SERVER);
01130 }
01131
01132 return true;
01133 }
01134
01135 DEF_CONSOLE_CMD(ConCompanies)
01136 {
01137 Company *c;
01138
01139 if (argc == 0) {
01140 IConsoleHelp("List the in-game details of all clients connected to the server. Usage 'companies'");
01141 return true;
01142 }
01143 NetworkCompanyStats company_stats[MAX_COMPANIES];
01144 NetworkPopulateCompanyStats(company_stats);
01145
01146 FOR_ALL_COMPANIES(c) {
01147
01148 char company_name[NETWORK_COMPANY_NAME_LENGTH];
01149 SetDParam(0, c->index);
01150 GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
01151
01152 char buffer[512];
01153 const NetworkCompanyStats *stats = &company_stats[c->index];
01154
01155 GetString(buffer, STR_00D1_DARK_BLUE + _company_colours[c->index], lastof(buffer));
01156 IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: %" OTTD_PRINTF64 "d Loan: %" OTTD_PRINTF64 "d Value: %" OTTD_PRINTF64 "d (T:%d, R:%d, P:%d, S:%d) %sprotected",
01157 c->index + 1, buffer, company_name, c->inaugurated_year, (int64)c->money, (int64)c->current_loan, (int64)CalculateCompanyValue(c),
01158 stats->num_vehicle[0],
01159 stats->num_vehicle[1] + stats->num_vehicle[2],
01160 stats->num_vehicle[3],
01161 stats->num_vehicle[4],
01162 StrEmpty(_network_company_states[c->index].password) ? "un" : "");
01163 }
01164
01165 return true;
01166 }
01167
01168 DEF_CONSOLE_CMD(ConSayCompany)
01169 {
01170 if (argc == 0) {
01171 IConsoleHelp("Chat to a certain company in a multiplayer game. Usage: 'say_company <company-no> \"<msg>\"'");
01172 IConsoleHelp("CompanyNo is the company that plays as company <companyno>, 1 through max_companies");
01173 return true;
01174 }
01175
01176 if (argc != 3) return false;
01177
01178 CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
01179 if (!IsValidCompanyID(company_id)) {
01180 IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
01181 return true;
01182 }
01183
01184 if (!_network_server) {
01185 NetworkClientSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2]);
01186 } else {
01187 NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2], CLIENT_ID_SERVER);
01188 }
01189
01190 return true;
01191 }
01192
01193 DEF_CONSOLE_CMD(ConSayClient)
01194 {
01195 if (argc == 0) {
01196 IConsoleHelp("Chat to a certain client in a multiplayer game. Usage: 'say_client <client-no> \"<msg>\"'");
01197 IConsoleHelp("For client-id's, see the command 'clients'");
01198 return true;
01199 }
01200
01201 if (argc != 3) return false;
01202
01203 if (!_network_server) {
01204 NetworkClientSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
01205 } else {
01206 NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], CLIENT_ID_SERVER);
01207 }
01208
01209 return true;
01210 }
01211
01212 extern void HashCurrentCompanyPassword(const char *password);
01213
01214
01215 bool NetworkChangeCompanyPassword(byte argc, char *argv[])
01216 {
01217 if (argc == 0) {
01218 IConsoleHelp("Change the password of your company. Usage: 'company_pw \"<password>\"'");
01219 IConsoleHelp("Use \"*\" to disable the password.");
01220 return true;
01221 }
01222
01223 if (!IsValidCompanyID(_local_company)) {
01224 IConsoleError("You have to own a company to make use of this command.");
01225 return false;
01226 }
01227
01228 if (argc != 1) return false;
01229
01230 if (strcmp(argv[0], "*") == 0) argv[0][0] = '\0';
01231
01232 if (!_network_server) {
01233 NetworkClientSetPassword(argv[0]);
01234 } else {
01235 HashCurrentCompanyPassword(argv[0]);
01236 }
01237
01238 IConsolePrintF(CC_WARNING, "'company_pw' changed to: %s", argv[0]);
01239
01240 return true;
01241 }
01242
01243 #endif
01244
01245 DEF_CONSOLE_CMD(ConPatch)
01246 {
01247 if (argc == 0) {
01248 IConsoleHelp("Change patch variables for all clients. Usage: 'patch <name> [<value>]'");
01249 IConsoleHelp("Omitting <value> will print out the current value of the patch-setting.");
01250 return true;
01