# command.cpp

Go to the documentation of this file.

    00001 /* $Id: command.cpp 19665 2010-04-17 22:27:49Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "openttd.h"
    00014 #include "landscape.h"
    00015 #include "gui.h"
    00016 #include "command_func.h"
    00017 #include "network/network.h"
    00018 #include "genworld.h"
    00019 #include "newgrf_storage.h"
    00020 #include "strings_func.h"
    00021 #include "gfx_func.h"
    00022 #include "functions.h"
    00023 #include "town.h"
    00024 #include "date_func.h"
    00025 #include "debug.h"
    00026 #include "company_func.h"
    00027 #include "company_base.h"
    00028 #include "signal_func.h"
    00029
    00030 #include "table/strings.h"
    00031
    00032 StringID _error_message;
    00033
    00034 CommandProc CmdBuildRailroadTrack;
    00035 CommandProc CmdRemoveRailroadTrack;
    00036 CommandProc CmdBuildSingleRail;
    00037 CommandProc CmdRemoveSingleRail;
    00038
    00039 CommandProc CmdLandscapeClear;
    00040
    00041 CommandProc CmdBuildBridge;
    00042
    00043 CommandProc CmdBuildRailStation;
    00044 CommandProc CmdRemoveFromRailStation;
    00045 CommandProc CmdConvertRail;
    00046
    00047 CommandProc CmdBuildSingleSignal;
    00048 CommandProc CmdRemoveSingleSignal;
    00049
    00050 CommandProc CmdTerraformLand;
    00051
    00052 CommandProc CmdPurchaseLandArea;
    00053 CommandProc CmdSellLandArea;
    00054
    00055 CommandProc CmdBuildTunnel;
    00056
    00057 CommandProc CmdBuildTrainDepot;
    00058 CommandProc CmdBuildRailWaypoint;
    00059 CommandProc CmdRenameWaypoint;
    00060 CommandProc CmdRemoveFromRailWaypoint;
    00061
    00062 CommandProc CmdBuildRoadStop;
    00063 CommandProc CmdRemoveRoadStop;
    00064
    00065 CommandProc CmdBuildLongRoad;
    00066 CommandProc CmdRemoveLongRoad;
    00067 CommandProc CmdBuildRoad;
    00068
    00069 CommandProc CmdBuildRoadDepot;
    00070
    00071 CommandProc CmdBuildAirport;
    00072
    00073 CommandProc CmdBuildDock;
    00074
    00075 CommandProc CmdBuildShipDepot;
    00076
    00077 CommandProc CmdBuildBuoy;
    00078
    00079 CommandProc CmdPlantTree;
    00080
    00081 CommandProc CmdBuildRailVehicle;
    00082 CommandProc CmdMoveRailVehicle;
    00083
    00084 CommandProc CmdSellRailWagon;
    00085
    00086 CommandProc CmdSendTrainToDepot;
    00087 CommandProc CmdForceTrainProceed;
    00088 CommandProc CmdReverseTrainDirection;
    00089
    00090 CommandProc CmdModifyOrder;
    00091 CommandProc CmdSkipToOrder;
    00092 CommandProc CmdDeleteOrder;
    00093 CommandProc CmdInsertOrder;
    00094 CommandProc CmdChangeServiceInt;
    00095 CommandProc CmdRestoreOrderIndex;
    00096
    00097 CommandProc CmdBuildIndustry;
    00098
    00099 CommandProc CmdBuildCompanyHQ;
    00100 CommandProc CmdSetCompanyManagerFace;
    00101 CommandProc CmdSetCompanyColour;
    00102
    00103 CommandProc CmdIncreaseLoan;
    00104 CommandProc CmdDecreaseLoan;
    00105
    00106 CommandProc CmdWantEnginePreview;
    00107
    00108 CommandProc CmdRenameVehicle;
    00109 CommandProc CmdRenameEngine;
    00110
    00111 CommandProc CmdRenameCompany;
    00112 CommandProc CmdRenamePresident;
    00113
    00114 CommandProc CmdRenameStation;
    00115
    00116 CommandProc CmdSellAircraft;
    00117 CommandProc CmdBuildAircraft;
    00118 CommandProc CmdSendAircraftToHangar;
    00119 CommandProc CmdRefitAircraft;
    00120
    00121 CommandProc CmdPlaceSign;
    00122 CommandProc CmdRenameSign;
    00123
    00124 CommandProc CmdBuildRoadVeh;
    00125 CommandProc CmdSellRoadVeh;
    00126 CommandProc CmdSendRoadVehToDepot;
    00127 CommandProc CmdTurnRoadVeh;
    00128 CommandProc CmdRefitRoadVeh;
    00129
    00130 CommandProc CmdPause;
    00131
    00132 CommandProc CmdBuyShareInCompany;
    00133 CommandProc CmdSellShareInCompany;
    00134 CommandProc CmdBuyCompany;
    00135
    00136 CommandProc CmdFoundTown;
    00137
    00138 CommandProc CmdRenameTown;
    00139 CommandProc CmdDoTownAction;
    00140
    00141 CommandProc CmdChangeSetting;
    00142 CommandProc CmdChangeCompanySetting;
    00143
    00144 CommandProc CmdSellShip;
    00145 CommandProc CmdBuildShip;
    00146 CommandProc CmdSendShipToDepot;
    00147 CommandProc CmdRefitShip;
    00148
    00149 CommandProc CmdOrderRefit;
    00150 CommandProc CmdCloneOrder;
    00151
    00152 CommandProc CmdClearArea;
    00153
    00154 CommandProc CmdGiveMoney;
    00155 CommandProc CmdMoneyCheat;
    00156 CommandProc CmdBuildCanal;
    00157 CommandProc CmdBuildLock;
    00158
    00159 CommandProc CmdCompanyCtrl;
    00160
    00161 CommandProc CmdLevelLand;
    00162
    00163 CommandProc CmdRefitRailVehicle;
    00164
    00165 CommandProc CmdBuildSignalTrack;
    00166 CommandProc CmdRemoveSignalTrack;
    00167
    00168 CommandProc CmdSetAutoReplace;
    00169
    00170 CommandProc CmdCloneVehicle;
    00171 CommandProc CmdStartStopVehicle;
    00172 CommandProc CmdMassStartStopVehicle;
    00173 CommandProc CmdAutoreplaceVehicle;
    00174 CommandProc CmdDepotSellAllVehicles;
    00175 CommandProc CmdDepotMassAutoReplace;
    00176
    00177 CommandProc CmdCreateGroup;
    00178 CommandProc CmdRenameGroup;
    00179 CommandProc CmdDeleteGroup;
    00180 CommandProc CmdAddVehicleGroup;
    00181 CommandProc CmdAddSharedVehicleGroup;
    00182 CommandProc CmdRemoveAllVehiclesGroup;
    00183 CommandProc CmdSetGroupReplaceProtection;
    00184
    00185 CommandProc CmdMoveOrder;
    00186 CommandProc CmdChangeTimetable;
    00187 CommandProc CmdSetVehicleOnTime;
    00188 CommandProc CmdAutofillTimetable;
    00189 CommandProc CmdSetTimetableStart;
    00190
    00191 #define DEF_CMD(proc, flags) {proc, #proc, flags}
    00192
    00200 static const Command _command_proc_table[] = {
    00201   DEF_CMD(CmdBuildRailroadTrack,       CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_RAILROAD_TRACK
    00202   DEF_CMD(CmdRemoveRailroadTrack,                     CMD_AUTO), // CMD_REMOVE_RAILROAD_TRACK
    00203   DEF_CMD(CmdBuildSingleRail,          CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_SINGLE_RAIL
    00204   DEF_CMD(CmdRemoveSingleRail,                        CMD_AUTO), // CMD_REMOVE_SINGLE_RAIL
    00205   DEF_CMD(CmdLandscapeClear,                                 0), // CMD_LANDSCAPE_CLEAR
    00206   DEF_CMD(CmdBuildBridge,                             CMD_AUTO), // CMD_BUILD_BRIDGE
    00207   DEF_CMD(CmdBuildRailStation,         CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_RAIL_STATION
    00208   DEF_CMD(CmdBuildTrainDepot,          CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_TRAIN_DEPOT
    00209   DEF_CMD(CmdBuildSingleSignal,                       CMD_AUTO), // CMD_BUILD_SIGNALS
    00210   DEF_CMD(CmdRemoveSingleSignal,                      CMD_AUTO), // CMD_REMOVE_SIGNALS
    00211   DEF_CMD(CmdTerraformLand,           CMD_ALL_TILES | CMD_AUTO), // CMD_TERRAFORM_LAND
    00212   DEF_CMD(CmdPurchaseLandArea,         CMD_NO_WATER | CMD_AUTO), // CMD_PURCHASE_LAND_AREA
    00213   DEF_CMD(CmdSellLandArea,                                   0), // CMD_SELL_LAND_AREA
    00214   DEF_CMD(CmdBuildTunnel,                             CMD_AUTO), // CMD_BUILD_TUNNEL
    00215   DEF_CMD(CmdRemoveFromRailStation,                          0), // CMD_REMOVE_FROM_RAIL_STATION
    00216   DEF_CMD(CmdConvertRail,                                    0), // CMD_CONVERT_RAILD
    00217   DEF_CMD(CmdBuildRailWaypoint,                              0), // CMD_BUILD_RAIL_WAYPOINT
    00218   DEF_CMD(CmdRenameWaypoint,                                 0), // CMD_RENAME_WAYPOINT
    00219   DEF_CMD(CmdRemoveFromRailWaypoint,                         0), // CMD_REMOVE_FROM_RAIL_WAYPOINT
    00220
    00221   DEF_CMD(CmdBuildRoadStop,            CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_ROAD_STOP
    00222   DEF_CMD(CmdRemoveRoadStop,                                 0), // CMD_REMOVE_ROAD_STOP
    00223   DEF_CMD(CmdBuildLongRoad,            CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_LONG_ROAD
    00224   DEF_CMD(CmdRemoveLongRoad,            CMD_NO_TEST | CMD_AUTO), // CMD_REMOVE_LONG_ROAD; towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed.
    00225   DEF_CMD(CmdBuildRoad,                CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_ROAD
    00226   DEF_CMD(CmdBuildRoadDepot,           CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_ROAD_DEPOT
    00227
    00228   DEF_CMD(CmdBuildAirport,             CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_AIRPORT
    00229   DEF_CMD(CmdBuildDock,                               CMD_AUTO), // CMD_BUILD_DOCK
    00230   DEF_CMD(CmdBuildShipDepot,                          CMD_AUTO), // CMD_BUILD_SHIP_DEPOT
    00231   DEF_CMD(CmdBuildBuoy,                               CMD_AUTO), // CMD_BUILD_BUOY
    00232   DEF_CMD(CmdPlantTree,                               CMD_AUTO), // CMD_PLANT_TREE
    00233   DEF_CMD(CmdBuildRailVehicle,                               0), // CMD_BUILD_RAIL_VEHICLE
    00234   DEF_CMD(CmdMoveRailVehicle,                                0), // CMD_MOVE_RAIL_VEHICLE
    00235
    00236   DEF_CMD(CmdSellRailWagon,                                  0), // CMD_SELL_RAIL_WAGON
    00237   DEF_CMD(CmdSendTrainToDepot,                               0), // CMD_SEND_TRAIN_TO_DEPOT
    00238   DEF_CMD(CmdForceTrainProceed,                              0), // CMD_FORCE_TRAIN_PROCEED
    00239   DEF_CMD(CmdReverseTrainDirection,                          0), // CMD_REVERSE_TRAIN_DIRECTION
    00240
    00241   DEF_CMD(CmdModifyOrder,                                    0), // CMD_MODIFY_ORDER
    00242   DEF_CMD(CmdSkipToOrder,                                    0), // CMD_SKIP_TO_ORDER
    00243   DEF_CMD(CmdDeleteOrder,                                    0), // CMD_DELETE_ORDER
    00244   DEF_CMD(CmdInsertOrder,                                    0), // CMD_INSERT_ORDER
    00245
    00246   DEF_CMD(CmdChangeServiceInt,                               0), // CMD_CHANGE_SERVICE_INT
    00247
    00248   DEF_CMD(CmdBuildIndustry,                                  0), // CMD_BUILD_INDUSTRY
    00249   DEF_CMD(CmdBuildCompanyHQ,           CMD_NO_WATER | CMD_AUTO), // CMD_BUILD_COMPANY_HQ
    00250   DEF_CMD(CmdSetCompanyManagerFace,                          0), // CMD_SET_COMPANY_MANAGER_FACE
    00251   DEF_CMD(CmdSetCompanyColour,                               0), // CMD_SET_COMPANY_COLOUR
    00252
    00253   DEF_CMD(CmdIncreaseLoan,                                   0), // CMD_INCREASE_LOAN
    00254   DEF_CMD(CmdDecreaseLoan,                                   0), // CMD_DECREASE_LOAN
    00255
    00256   DEF_CMD(CmdWantEnginePreview,                              0), // CMD_WANT_ENGINE_PREVIEW
    00257
    00258   DEF_CMD(CmdRenameVehicle,                                  0), // CMD_RENAME_VEHICLE
    00259   DEF_CMD(CmdRenameEngine,                                   0), // CMD_RENAME_ENGINE
    00260
    00261   DEF_CMD(CmdRenameCompany,                                  0), // CMD_RENAME_COMPANY
    00262   DEF_CMD(CmdRenamePresident,                                0), // CMD_RENAME_PRESIDENT
    00263
    00264   DEF_CMD(CmdRenameStation,                                  0), // CMD_RENAME_STATION
    00265
    00266   DEF_CMD(CmdSellAircraft,                                   0), // CMD_SELL_AIRCRAFT
    00267
    00268   DEF_CMD(CmdBuildAircraft,                                  0), // CMD_BUILD_AIRCRAFT
    00269   DEF_CMD(CmdSendAircraftToHangar,                           0), // CMD_SEND_AIRCRAFT_TO_HANGAR
    00270   DEF_CMD(CmdRefitAircraft,                                  0), // CMD_REFIT_AIRCRAFT
    00271
    00272   DEF_CMD(CmdPlaceSign,                                      0), // CMD_PLACE_SIGN
    00273   DEF_CMD(CmdRenameSign,                                     0), // CMD_RENAME_SIGN
    00274
    00275   DEF_CMD(CmdBuildRoadVeh,                                   0), // CMD_BUILD_ROAD_VEH
    00276   DEF_CMD(CmdSellRoadVeh,                                    0), // CMD_SELL_ROAD_VEH
    00277   DEF_CMD(CmdSendRoadVehToDepot,                             0), // CMD_SEND_ROADVEH_TO_DEPOT
    00278   DEF_CMD(CmdTurnRoadVeh,                                    0), // CMD_TURN_ROADVEH
    00279   DEF_CMD(CmdRefitRoadVeh,                                   0), // CMD_REFIT_ROAD_VEH
    00280
    00281   DEF_CMD(CmdPause,                                 CMD_SERVER), // CMD_PAUSE
    00282
    00283   DEF_CMD(CmdBuyShareInCompany,                              0), // CMD_BUY_SHARE_IN_COMPANY
    00284   DEF_CMD(CmdSellShareInCompany,                             0), // CMD_SELL_SHARE_IN_COMPANY
    00285   DEF_CMD(CmdBuyCompany,                                     0), // CMD_BUY_COMANY
    00286
    00287   DEF_CMD(CmdFoundTown,                            CMD_NO_TEST), // CMD_FOUND_TOWN; founding random town can fail only in exec run
    00288   DEF_CMD(CmdRenameTown,                            CMD_SERVER), // CMD_RENAME_TOWN
    00289   DEF_CMD(CmdDoTownAction,                                   0), // CMD_DO_TOWN_ACTION
    00290
    00291   DEF_CMD(CmdSellShip,                                       0), // CMD_SELL_SHIP
    00292   DEF_CMD(CmdBuildShip,                                      0), // CMD_BUILD_SHIP
    00293   DEF_CMD(CmdSendShipToDepot,                                0), // CMD_SEND_SHIP_TO_DEPOT
    00294   DEF_CMD(CmdRefitShip,                                      0), // CMD_REFIT_SHIP
    00295
    00296   DEF_CMD(CmdOrderRefit,                                     0), // CMD_ORDER_REFIT
    00297   DEF_CMD(CmdCloneOrder,                                     0), // CMD_CLONE_ORDER
    00298
    00299   DEF_CMD(CmdClearArea,                            CMD_NO_TEST), // CMD_CLEAR_AREA; destroying multi-tile houses makes town rating differ between test and execution
    00300
    00301   DEF_CMD(CmdMoneyCheat,                           CMD_OFFLINE), // CMD_MONEY_CHEAT
    00302   DEF_CMD(CmdBuildCanal,                              CMD_AUTO), // CMD_BUILD_CANAL
    00303   DEF_CMD(CmdCompanyCtrl,                        CMD_SPECTATOR), // CMD_COMPANY_CTRL
    00304
    00305   DEF_CMD(CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO), // CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once
    00306
    00307   DEF_CMD(CmdRefitRailVehicle,                               0), // CMD_REFIT_RAIL_VEHICLE
    00308   DEF_CMD(CmdRestoreOrderIndex,                              0), // CMD_RESTORE_ORDER_INDEX
    00309   DEF_CMD(CmdBuildLock,                               CMD_AUTO), // CMD_BUILD_LOCK
    00310
    00311   DEF_CMD(CmdBuildSignalTrack,                        CMD_AUTO), // CMD_BUILD_SIGNAL_TRACK
    00312   DEF_CMD(CmdRemoveSignalTrack,                       CMD_AUTO), // CMD_REMOVE_SIGNAL_TRACK
    00313
    00314   DEF_CMD(CmdGiveMoney,                                      0), // CMD_GIVE_MONEY
    00315   DEF_CMD(CmdChangeSetting,                         CMD_SERVER), // CMD_CHANGE_SETTING
    00316   DEF_CMD(CmdChangeCompanySetting,                           0), // CMD_CHANGE_COMPANY_SETTING
    00317   DEF_CMD(CmdSetAutoReplace,                                 0), // CMD_SET_AUTOREPLACE
    00318   DEF_CMD(CmdCloneVehicle,                         CMD_NO_TEST), // CMD_CLONE_VEHICLE; NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost
    00319   DEF_CMD(CmdStartStopVehicle,                               0), // CMD_START_STOP_VEHICLE
    00320   DEF_CMD(CmdMassStartStopVehicle,                           0), // CMD_MASS_START_STOP
    00321   DEF_CMD(CmdAutoreplaceVehicle,                             0), // CMD_AUTOREPLACE_VEHICLE
    00322   DEF_CMD(CmdDepotSellAllVehicles,                           0), // CMD_DEPOT_SELL_ALL_VEHICLES
    00323   DEF_CMD(CmdDepotMassAutoReplace,                           0), // CMD_DEPOT_MASS_AUTOREPLACE
    00324   DEF_CMD(CmdCreateGroup,                                    0), // CMD_CREATE_GROUP
    00325   DEF_CMD(CmdDeleteGroup,                                    0), // CMD_DELETE_GROUP
    00326   DEF_CMD(CmdRenameGroup,                                    0), // CMD_RENAME_GROUP
    00327   DEF_CMD(CmdAddVehicleGroup,                                0), // CMD_ADD_VEHICLE_GROUP
    00328   DEF_CMD(CmdAddSharedVehicleGroup,                          0), // CMD_ADD_SHARE_VEHICLE_GROUP
    00329   DEF_CMD(CmdRemoveAllVehiclesGroup,                         0), // CMD_REMOVE_ALL_VEHICLES_GROUP
    00330   DEF_CMD(CmdSetGroupReplaceProtection,                      0), // CMD_SET_GROUP_REPLACE_PROTECTION
    00331   DEF_CMD(CmdMoveOrder,                                      0), // CMD_MOVE_ORDER
    00332   DEF_CMD(CmdChangeTimetable,                                0), // CMD_CHANGE_TIMETABLE
    00333   DEF_CMD(CmdSetVehicleOnTime,                               0), // CMD_SET_VEHICLE_ON_TIME
    00334   DEF_CMD(CmdAutofillTimetable,                              0), // CMD_AUTOFILL_TIMETABLE
    00335   DEF_CMD(CmdSetTimetableStart,                              0), // CMD_SET_TIMETABLE_START
    00336 };
    00337
    00344 bool IsValidCommand(uint32 cmd)
    00345 {
    00346   cmd &= CMD_ID_MASK;
    00347
    00348   return
    00349     cmd < lengthof(_command_proc_table) &&
    00350     _command_proc_table[cmd].proc != NULL;
    00351 }
    00352
    00360 byte GetCommandFlags(uint32 cmd)
    00361 {
    00362   assert(IsValidCommand(cmd));
    00363
    00364   return _command_proc_table[cmd & CMD_ID_MASK].flags;
    00365 }
    00366
    00374 const char *GetCommandName(uint32 cmd)
    00375 {
    00376   assert(IsValidCommand(cmd));
    00377
    00378   return _command_proc_table[cmd & CMD_ID_MASK].name;
    00379 }
    00380
    00381 static int _docommand_recursive = 0;
    00382
    00391 CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
    00392 {
    00393   return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text);
    00394 }
    00395
    00409 CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text)
    00410 {
    00411   CommandCost res;
    00412
    00413   /* Do not even think about executing out-of-bounds tile-commands */
    00414   if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
    00415
    00416   /* Chop of any CMD_MSG or other flags; we don't need those here */
    00417   CommandProc *proc = _command_proc_table[cmd & CMD_ID_MASK].proc;
    00418
    00419   if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
    00420
    00421   _docommand_recursive++;
    00422
    00423   /* only execute the test call if it's toplevel, or we're not execing. */
    00424   if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
    00425     SetTownRatingTestMode(true);
    00426     res = proc(tile, flags & ~DC_EXEC, p1, p2, text);
    00427     SetTownRatingTestMode(false);
    00428     if (res.Failed()) {
    00429       goto error;
    00430     }
    00431
    00432     if (_docommand_recursive == 1 &&
    00433         !(flags & DC_QUERY_COST) &&
    00434         !(flags & DC_BANKRUPT) &&
    00435         !CheckCompanyHasMoney(res)) {
    00436       goto error;
    00437     }
    00438
    00439     if (!(flags & DC_EXEC)) {
    00440       _docommand_recursive--;
    00441       return res;
    00442     }
    00443   }
    00444
    00445   /* Execute the command here. All cost-relevant functions set the expenses type
    00446    * themselves to the cost object at some point */
    00447   res = proc(tile, flags, p1, p2, text);
    00448   if (res.Failed()) {
    00449 error:
    00450     res.SetGlobalErrorMessage();
    00451     _docommand_recursive--;
    00452     return CMD_ERROR;
    00453   }
    00454
    00455   /* if toplevel, subtract the money. */
    00456   if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) {
    00457     SubtractMoneyFromCompany(res);
    00458   }
    00459
    00460   return res;
    00461 }
    00462
    00470 Money GetAvailableMoneyForCommand()
    00471 {
    00472   CompanyID company = _current_company;
    00473   if (!Company::IsValidID(company)) return INT64_MAX;
    00474   return Company::Get(company)->money;
    00475 }
    00476
    00483 bool DoCommandP(const CommandContainer *container, bool my_cmd)
    00484 {
    00485   return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text, my_cmd);
    00486 }
    00487
    00503 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd)
    00504 {
    00505   /* Cost estimation is generally only done when the
    00506    * local user presses shift while doing somthing.
    00507    * However, in case of incoming network commands,
    00508    * map generation of the pause button we do want
    00509    * to execute. */
    00510   bool estimate_only = _shift_pressed && IsLocalCompany() &&
    00511       !IsGeneratingWorld() &&
    00512       !(cmd & CMD_NETWORK_COMMAND) &&
    00513       (cmd & CMD_ID_MASK) != CMD_PAUSE;
    00514
    00515   /* We're only sending the command, so don't do
    00516    * fancy things for 'success'. */
    00517   bool only_sending = _networking && !(cmd & CMD_NETWORK_COMMAND);
    00518
    00519   /* Where to show the message? */
    00520   int x = TileX(tile) * TILE_SIZE;
    00521   int y = TileY(tile) * TILE_SIZE;
    00522
    00523   CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only);
    00524   if (res.Failed()) {
    00525     res.SetGlobalErrorMessage();
    00526
    00527     /* Only show the error when it's for us. */
    00528     StringID error_part1 = GB(cmd, 16, 16);
    00529     if (estimate_only || (IsLocalCompany() && error_part1 != 0 && my_cmd)) {
    00530       ShowErrorMessage(error_part1, _error_message, x, y);
    00531     }
    00532   } else if (estimate_only) {
    00533     ShowEstimatedCostOrIncome(res.GetCost(), x, y);
    00534   } else if (!only_sending && res.GetCost() != 0 && tile != 0 && IsLocalCompany() && _game_mode != GM_EDITOR) {
    00535     /* Only show the cost animation when we did actually
    00536      * execute the command, i.e. we're not sending it to
    00537      * the server, when it has cost the local company
    00538      * something. Furthermore in the editor there is no
    00539      * concept of cost, so don't show it there either. */
    00540     ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res.GetCost());
    00541   }
    00542
    00543   if (!estimate_only && !only_sending && callback != NULL) {
    00544     callback(res, tile, p1, p2);
    00545   }
    00546
    00547   return res.Succeeded();
    00548 }
    00549
    00550
    00556 #define return_dcpi(cmd, clear) { _docommand_recursive = 0; ClearStorageChanges(clear); return cmd; }
    00557
    00571 CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only)
    00572 {
    00573   /* Prevent recursion; it gives a mess over the network */
    00574   assert(_docommand_recursive == 0);
    00575   _docommand_recursive = 1;
    00576
    00577   /* Reset the state. */
    00578   _error_message = INVALID_STRING_ID;
    00579   _additional_cash_required = 0;
    00580
    00581   /* Get pointer to command handler */
    00582   byte cmd_id = cmd & CMD_ID_MASK;
    00583   assert(cmd_id < lengthof(_command_proc_table));
    00584
    00585   CommandProc *proc = _command_proc_table[cmd_id].proc;
    00586   /* Shouldn't happen, but you never know when someone adds
    00587    * NULLs to the _command_proc_table. */
    00588   assert(proc != NULL);
    00589
    00590   /* Command flags are used internally */
    00591   uint cmd_flags = GetCommandFlags(cmd);
    00592   /* Flags get send to the DoCommand */
    00593   DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
    00594
    00595   /* Do not even think about executing out-of-bounds tile-commands */
    00596   if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (cmd_flags & CMD_ALL_TILES) == 0))) return_dcpi(CMD_ERROR, false);
    00597
    00598   /* Always execute server and spectator commands as spectator */
    00599   if (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) _current_company = COMPANY_SPECTATOR;
    00600
    00601   CompanyID old_company = _current_company;
    00602
    00603   /* If the company isn't valid it may only do server command or start a new company!
    00604    * The server will ditch any server commands a client sends to it, so effectively
    00605    * this guards the server from executing functions for an invalid company. */
    00606   if (_game_mode == GM_NORMAL && (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) == 0 && !Company::IsValidID(_current_company)) {
    00607     return_dcpi(CMD_ERROR, false);
    00608   }
    00609
    00610   bool test_and_exec_can_differ = (cmd_flags & CMD_NO_TEST) != 0;
    00611   bool skip_test = _networking && (cmd & CMD_NO_TEST_IF_IN_NETWORK) != 0;
    00612
    00613   /* Do we need to do a test run?
    00614    * Basically we need to always do this, except when
    00615    * the no-test-in-network flag is giving and we're
    00616    * in a network game (e.g. restoring orders would
    00617    * fail this test because the first order does not
    00618    * exist yet when inserting the second, giving that
    00619    * a wrong insert location and ignoring the command
    00620    * and thus breaking restoring). However, when we
    00621    * just want to do cost estimation we don't care
    00622    * because it's only done once anyway. */
    00623   CommandCost res;
    00624   if (estimate_only || !skip_test) {
    00625     /* Test the command. */
    00626     SetTownRatingTestMode(true);
    00627     res = proc(tile, flags, p1, p2, text);
    00628     SetTownRatingTestMode(false);
    00629
    00630     /* Make sure we're not messing things up here. */
    00631     assert(cmd_id == CMD_COMPANY_CTRL || old_company == _current_company);
    00632
    00633     /* If the command fails, we're doing an estimate
    00634      * or the player does not have enough money
    00635      * (unless it's a command where the test and
    00636      * execution phase might return different costs)
    00637      * we bail out here. */
    00638     if (res.Failed() || estimate_only ||
    00639         (!test_and_exec_can_differ && !CheckCompanyHasMoney(res))) {
    00640       return_dcpi(res, false);
    00641     }
    00642   }
    00643
    00644 #ifdef ENABLE_NETWORK
    00645   /*
    00646    * If we are in network, and the command is not from the network
    00647    * send it to the command-queue and abort execution
    00648    */
    00649   if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
    00650     NetworkSend_Command(tile, p1, p2, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company);
    00651
    00652     /* Don't return anything special here; no error, no costs.
    00653      * This way it's not handled by DoCommand and only the
    00654      * actual execution of the command causes messages. Also
    00655      * reset the storages as we've not executed the command. */
    00656     return_dcpi(CommandCost(), false);
    00657   }
    00658 #endif /* ENABLE_NETWORK */
    00659   DEBUG(desync, 1, "cmd: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, GetCommandName(cmd));
    00660
    00661   /* Actually try and execute the command. If no cost-type is given
    00662    * use the construction one */
    00663   CommandCost res2 = proc(tile, flags | DC_EXEC, p1, p2, text);
    00664
    00665   /* Make sure nothing bad happened, like changing the current company. */
    00666   assert(cmd_id == CMD_COMPANY_CTRL || old_company == _current_company);
    00667
    00668   /* If the test and execution can differ, or we skipped the test
    00669    * we have to check the return of the command. Otherwise we can
    00670    * check whether the test and execution have yielded the same
    00671    * result, i.e. cost and error state are the same. */
    00672   if (!test_and_exec_can_differ && !skip_test) {
    00673     assert(res.GetCost() == res2.GetCost() && res.Failed() == res2.Failed()); // sanity check
    00674   } else if (res2.Failed()) {
    00675     return_dcpi(res2, false);
    00676   }
    00677
    00678   /* If we're needing more money and we haven't done
    00679    * anything yet, ask for the money! */
    00680   if (_additional_cash_required != 0 && res2.GetCost() == 0) {
    00681     /* It could happen we removed rail, thus gained money, and deleted something else.
    00682      * So make sure the signal buffer is empty even in this case */
    00683     UpdateSignalsInBuffer();
    00684     SetDParam(0, _additional_cash_required);
    00685     return_dcpi(CommandCost(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY), false);
    00686   }
    00687
    00688   /* update last build coordinate of company. */
    00689   if (tile != 0) {
    00690     Company *c = Company::GetIfValid(_current_company);
    00691     if (c != NULL) c->last_build_coordinate = tile;
    00692   }
    00693
    00694   SubtractMoneyFromCompany(res2);
    00695
    00696   /* update signals if needed */
    00697   UpdateSignalsInBuffer();
    00698
    00699   return_dcpi(res2, true);
    00700 }
    00701 #undef return_dcpi
    00702
    00703
    00709 void CommandCost::AddCost(const CommandCost &ret)
    00710 {
    00711   this->AddCost(ret.cost);
    00712   if (this->success && !ret.success) {
    00713     this->message = ret.message;
    00714     this->success = false;
    00715   }
    00716 }