src/command.cpp
changeset 5584 1111b4d36e35
parent 5580 b7e597116b9c
child 5587 167d9a91ef02
equal deleted inserted replaced
5583:136d8764c7e6 5584:1111b4d36e35
       
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "table/strings.h"
       
     6 #include "functions.h"
       
     7 #include "map.h"
       
     8 #include "gui.h"
       
     9 #include "command.h"
       
    10 #include "player.h"
       
    11 #include "network/network.h"
       
    12 #include "variables.h"
       
    13 #include "genworld.h"
       
    14 
       
    15 const char* _cmd_text = NULL;
       
    16 
       
    17 #define DEF_COMMAND(yyyy) int32 yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
       
    18 
       
    19 DEF_COMMAND(CmdBuildRailroadTrack);
       
    20 DEF_COMMAND(CmdRemoveRailroadTrack);
       
    21 DEF_COMMAND(CmdBuildSingleRail);
       
    22 DEF_COMMAND(CmdRemoveSingleRail);
       
    23 
       
    24 DEF_COMMAND(CmdLandscapeClear);
       
    25 
       
    26 DEF_COMMAND(CmdBuildBridge);
       
    27 
       
    28 DEF_COMMAND(CmdBuildRailroadStation);
       
    29 DEF_COMMAND(CmdRemoveFromRailroadStation);
       
    30 DEF_COMMAND(CmdConvertRail);
       
    31 
       
    32 DEF_COMMAND(CmdBuildSingleSignal);
       
    33 DEF_COMMAND(CmdRemoveSingleSignal);
       
    34 
       
    35 DEF_COMMAND(CmdTerraformLand);
       
    36 
       
    37 DEF_COMMAND(CmdPurchaseLandArea);
       
    38 DEF_COMMAND(CmdSellLandArea);
       
    39 
       
    40 DEF_COMMAND(CmdBuildTunnel);
       
    41 
       
    42 DEF_COMMAND(CmdBuildTrainDepot);
       
    43 DEF_COMMAND(CmdBuildTrainWaypoint);
       
    44 DEF_COMMAND(CmdRenameWaypoint);
       
    45 DEF_COMMAND(CmdRemoveTrainWaypoint);
       
    46 
       
    47 DEF_COMMAND(CmdBuildRoadStop);
       
    48 
       
    49 DEF_COMMAND(CmdBuildLongRoad);
       
    50 DEF_COMMAND(CmdRemoveLongRoad);
       
    51 DEF_COMMAND(CmdBuildRoad);
       
    52 DEF_COMMAND(CmdRemoveRoad);
       
    53 
       
    54 DEF_COMMAND(CmdBuildRoadDepot);
       
    55 
       
    56 DEF_COMMAND(CmdBuildAirport);
       
    57 
       
    58 DEF_COMMAND(CmdBuildDock);
       
    59 
       
    60 DEF_COMMAND(CmdBuildShipDepot);
       
    61 
       
    62 DEF_COMMAND(CmdBuildBuoy);
       
    63 
       
    64 DEF_COMMAND(CmdPlantTree);
       
    65 
       
    66 DEF_COMMAND(CmdBuildRailVehicle);
       
    67 DEF_COMMAND(CmdMoveRailVehicle);
       
    68 
       
    69 DEF_COMMAND(CmdStartStopTrain);
       
    70 
       
    71 DEF_COMMAND(CmdSellRailWagon);
       
    72 
       
    73 DEF_COMMAND(CmdSendTrainToDepot);
       
    74 DEF_COMMAND(CmdForceTrainProceed);
       
    75 DEF_COMMAND(CmdReverseTrainDirection);
       
    76 
       
    77 DEF_COMMAND(CmdModifyOrder);
       
    78 DEF_COMMAND(CmdSkipOrder);
       
    79 DEF_COMMAND(CmdDeleteOrder);
       
    80 DEF_COMMAND(CmdInsertOrder);
       
    81 DEF_COMMAND(CmdChangeServiceInt);
       
    82 DEF_COMMAND(CmdRestoreOrderIndex);
       
    83 
       
    84 DEF_COMMAND(CmdBuildIndustry);
       
    85 
       
    86 DEF_COMMAND(CmdBuildCompanyHQ);
       
    87 DEF_COMMAND(CmdSetPlayerFace);
       
    88 DEF_COMMAND(CmdSetPlayerColor);
       
    89 
       
    90 DEF_COMMAND(CmdIncreaseLoan);
       
    91 DEF_COMMAND(CmdDecreaseLoan);
       
    92 
       
    93 DEF_COMMAND(CmdWantEnginePreview);
       
    94 
       
    95 DEF_COMMAND(CmdNameVehicle);
       
    96 DEF_COMMAND(CmdRenameEngine);
       
    97 
       
    98 DEF_COMMAND(CmdChangeCompanyName);
       
    99 DEF_COMMAND(CmdChangePresidentName);
       
   100 
       
   101 DEF_COMMAND(CmdRenameStation);
       
   102 
       
   103 DEF_COMMAND(CmdSellAircraft);
       
   104 DEF_COMMAND(CmdStartStopAircraft);
       
   105 DEF_COMMAND(CmdBuildAircraft);
       
   106 DEF_COMMAND(CmdSendAircraftToHangar);
       
   107 DEF_COMMAND(CmdRefitAircraft);
       
   108 
       
   109 DEF_COMMAND(CmdPlaceSign);
       
   110 DEF_COMMAND(CmdRenameSign);
       
   111 
       
   112 DEF_COMMAND(CmdBuildRoadVeh);
       
   113 DEF_COMMAND(CmdStartStopRoadVeh);
       
   114 DEF_COMMAND(CmdSellRoadVeh);
       
   115 DEF_COMMAND(CmdSendRoadVehToDepot);
       
   116 DEF_COMMAND(CmdTurnRoadVeh);
       
   117 DEF_COMMAND(CmdRefitRoadVeh);
       
   118 
       
   119 DEF_COMMAND(CmdPause);
       
   120 
       
   121 DEF_COMMAND(CmdBuyShareInCompany);
       
   122 DEF_COMMAND(CmdSellShareInCompany);
       
   123 DEF_COMMAND(CmdBuyCompany);
       
   124 
       
   125 DEF_COMMAND(CmdBuildTown);
       
   126 
       
   127 DEF_COMMAND(CmdRenameTown);
       
   128 DEF_COMMAND(CmdDoTownAction);
       
   129 
       
   130 DEF_COMMAND(CmdSetRoadDriveSide);
       
   131 
       
   132 DEF_COMMAND(CmdChangeDifficultyLevel);
       
   133 DEF_COMMAND(CmdChangePatchSetting);
       
   134 
       
   135 DEF_COMMAND(CmdStartStopShip);
       
   136 DEF_COMMAND(CmdSellShip);
       
   137 DEF_COMMAND(CmdBuildShip);
       
   138 DEF_COMMAND(CmdSendShipToDepot);
       
   139 DEF_COMMAND(CmdRefitShip);
       
   140 
       
   141 DEF_COMMAND(CmdOrderRefit);
       
   142 DEF_COMMAND(CmdCloneOrder);
       
   143 
       
   144 DEF_COMMAND(CmdClearArea);
       
   145 
       
   146 DEF_COMMAND(CmdGiveMoney);
       
   147 DEF_COMMAND(CmdMoneyCheat);
       
   148 DEF_COMMAND(CmdBuildCanal);
       
   149 DEF_COMMAND(CmdBuildLock);
       
   150 
       
   151 DEF_COMMAND(CmdPlayerCtrl);
       
   152 
       
   153 DEF_COMMAND(CmdLevelLand);
       
   154 
       
   155 DEF_COMMAND(CmdRefitRailVehicle);
       
   156 
       
   157 DEF_COMMAND(CmdBuildSignalTrack);
       
   158 DEF_COMMAND(CmdRemoveSignalTrack);
       
   159 
       
   160 DEF_COMMAND(CmdSetAutoReplace);
       
   161 
       
   162 DEF_COMMAND(CmdCloneVehicle);
       
   163 DEF_COMMAND(CmdMassStartStopVehicle);
       
   164 DEF_COMMAND(CmdDepotSellAllVehicles);
       
   165 DEF_COMMAND(CmdDepotMassAutoReplace);
       
   166 
       
   167 /* The master command table */
       
   168 static const Command _command_proc_table[] = {
       
   169 	{CmdBuildRailroadTrack,                  0}, /*   0 */
       
   170 	{CmdRemoveRailroadTrack,                 0}, /*   1 */
       
   171 	{CmdBuildSingleRail,                     0}, /*   2 */
       
   172 	{CmdRemoveSingleRail,                    0}, /*   3 */
       
   173 	{CmdLandscapeClear,                      0}, /*   4 */
       
   174 	{CmdBuildBridge,                         0}, /*   5 */
       
   175 	{CmdBuildRailroadStation,                0}, /*   6 */
       
   176 	{CmdBuildTrainDepot,                     0}, /*   7 */
       
   177 	{CmdBuildSingleSignal,                   0}, /*   8 */
       
   178 	{CmdRemoveSingleSignal,                  0}, /*   9 */
       
   179 	{CmdTerraformLand,                       0}, /*  10 */
       
   180 	{CmdPurchaseLandArea,                    0}, /*  11 */
       
   181 	{CmdSellLandArea,                        0}, /*  12 */
       
   182 	{CmdBuildTunnel,                         0}, /*  13 */
       
   183 	{CmdRemoveFromRailroadStation,           0}, /*  14 */
       
   184 	{CmdConvertRail,                         0}, /*  15 */
       
   185 	{CmdBuildTrainWaypoint,                  0}, /*  16 */
       
   186 	{CmdRenameWaypoint,                      0}, /*  17 */
       
   187 	{CmdRemoveTrainWaypoint,                 0}, /*  18 */
       
   188 	{NULL,                                   0}, /*  19 */
       
   189 	{NULL,                                   0}, /*  20 */
       
   190 	{CmdBuildRoadStop,                       0}, /*  21 */
       
   191 	{NULL,                                   0}, /*  22 */
       
   192 	{CmdBuildLongRoad,                       0}, /*  23 */
       
   193 	{CmdRemoveLongRoad,                      0}, /*  24 */
       
   194 	{CmdBuildRoad,                           0}, /*  25 */
       
   195 	{CmdRemoveRoad,                          0}, /*  26 */
       
   196 	{CmdBuildRoadDepot,                      0}, /*  27 */
       
   197 	{NULL,                                   0}, /*  28 */
       
   198 	{CmdBuildAirport,                        0}, /*  29 */
       
   199 	{CmdBuildDock,                           0}, /*  30 */
       
   200 	{CmdBuildShipDepot,                      0}, /*  31 */
       
   201 	{CmdBuildBuoy,                           0}, /*  32 */
       
   202 	{CmdPlantTree,                           0}, /*  33 */
       
   203 	{CmdBuildRailVehicle,                    0}, /*  34 */
       
   204 	{CmdMoveRailVehicle,                     0}, /*  35 */
       
   205 	{CmdStartStopTrain,                      0}, /*  36 */
       
   206 	{NULL,                                   0}, /*  37 */
       
   207 	{CmdSellRailWagon,                       0}, /*  38 */
       
   208 	{CmdSendTrainToDepot,                    0}, /*  39 */
       
   209 	{CmdForceTrainProceed,                   0}, /*  40 */
       
   210 	{CmdReverseTrainDirection,               0}, /*  41 */
       
   211 
       
   212 	{CmdModifyOrder,                         0}, /*  42 */
       
   213 	{CmdSkipOrder,                           0}, /*  43 */
       
   214 	{CmdDeleteOrder,                         0}, /*  44 */
       
   215 	{CmdInsertOrder,                         0}, /*  45 */
       
   216 
       
   217 	{CmdChangeServiceInt,                    0}, /*  46 */
       
   218 
       
   219 	{CmdBuildIndustry,                       0}, /*  47 */
       
   220 	{CmdBuildCompanyHQ,                      0}, /*  48 */
       
   221 	{CmdSetPlayerFace,                       0}, /*  49 */
       
   222 	{CmdSetPlayerColor,                      0}, /*  50 */
       
   223 
       
   224 	{CmdIncreaseLoan,                        0}, /*  51 */
       
   225 	{CmdDecreaseLoan,                        0}, /*  52 */
       
   226 
       
   227 	{CmdWantEnginePreview,                   0}, /*  53 */
       
   228 
       
   229 	{CmdNameVehicle,                         0}, /*  54 */
       
   230 	{CmdRenameEngine,                        0}, /*  55 */
       
   231 
       
   232 	{CmdChangeCompanyName,                   0}, /*  56 */
       
   233 	{CmdChangePresidentName,                 0}, /*  57 */
       
   234 
       
   235 	{CmdRenameStation,                       0}, /*  58 */
       
   236 
       
   237 	{CmdSellAircraft,                        0}, /*  59 */
       
   238 	{CmdStartStopAircraft,                   0}, /*  60 */
       
   239 
       
   240 	{CmdBuildAircraft,                       0}, /*  61 */
       
   241 	{CmdSendAircraftToHangar,                0}, /*  62 */
       
   242 	{NULL,                                   0}, /*  63 */
       
   243 	{CmdRefitAircraft,                       0}, /*  64 */
       
   244 
       
   245 	{CmdPlaceSign,                           0}, /*  65 */
       
   246 	{CmdRenameSign,                          0}, /*  66 */
       
   247 
       
   248 	{CmdBuildRoadVeh,                        0}, /*  67 */
       
   249 	{CmdStartStopRoadVeh,                    0}, /*  68 */
       
   250 	{CmdSellRoadVeh,                         0}, /*  69 */
       
   251 	{CmdSendRoadVehToDepot,                  0}, /*  70 */
       
   252 	{CmdTurnRoadVeh,                         0}, /*  71 */
       
   253 	{CmdRefitRoadVeh,                        0}, /*  72 */
       
   254 
       
   255 	{CmdPause,                      CMD_SERVER}, /*  73 */
       
   256 
       
   257 	{CmdBuyShareInCompany,                   0}, /*  74 */
       
   258 	{CmdSellShareInCompany,                  0}, /*  75 */
       
   259 	{CmdBuyCompany,                          0}, /*  76 */
       
   260 
       
   261 	{CmdBuildTown,                 CMD_OFFLINE}, /*  77 */
       
   262 	{NULL,                                   0}, /*  78 */
       
   263 	{NULL,                                   0}, /*  79 */
       
   264 	{CmdRenameTown,                 CMD_SERVER}, /*  80 */
       
   265 	{CmdDoTownAction,                        0}, /*  81 */
       
   266 
       
   267 	{CmdSetRoadDriveSide,           CMD_SERVER}, /*  82 */
       
   268 	{NULL,                                   0}, /*  83 */
       
   269 	{NULL,                                   0}, /*  84 */
       
   270 	{CmdChangeDifficultyLevel,      CMD_SERVER}, /*  85 */
       
   271 
       
   272 	{CmdStartStopShip,                       0}, /*  86 */
       
   273 	{CmdSellShip,                            0}, /*  87 */
       
   274 	{CmdBuildShip,                           0}, /*  88 */
       
   275 	{CmdSendShipToDepot,                     0}, /*  89 */
       
   276 	{NULL,                                   0}, /*  90 */
       
   277 	{CmdRefitShip,                           0}, /*  91 */
       
   278 
       
   279 	{NULL,                                   0}, /*  92 */
       
   280 	{NULL,                                   0}, /*  93 */
       
   281 	{NULL,                                   0}, /*  94 */
       
   282 	{NULL,                                   0}, /*  95 */
       
   283 	{NULL,                                   0}, /*  96 */
       
   284 	{NULL,                                   0}, /*  97 */
       
   285 
       
   286 	{CmdOrderRefit,                          0}, /*  98 */
       
   287 	{CmdCloneOrder,                          0}, /*  99 */
       
   288 
       
   289 	{CmdClearArea,                           0}, /* 100 */
       
   290 	{NULL,                                   0}, /* 101 */
       
   291 
       
   292 	{CmdMoneyCheat,                CMD_OFFLINE}, /* 102 */
       
   293 	{CmdBuildCanal,                          0}, /* 103 */
       
   294 	{CmdPlayerCtrl,                          0}, /* 104 */
       
   295 
       
   296 	{CmdLevelLand,                           0}, /* 105 */
       
   297 
       
   298 	{CmdRefitRailVehicle,                    0}, /* 106 */
       
   299 	{CmdRestoreOrderIndex,                   0}, /* 107 */
       
   300 	{CmdBuildLock,                           0}, /* 108 */
       
   301 	{NULL,                                   0}, /* 109 */
       
   302 	{CmdBuildSignalTrack,                    0}, /* 110 */
       
   303 	{CmdRemoveSignalTrack,                   0}, /* 111 */
       
   304 	{NULL,                                   0}, /* 112 */
       
   305 	{CmdGiveMoney,                           0}, /* 113 */
       
   306 	{CmdChangePatchSetting,         CMD_SERVER}, /* 114 */
       
   307 	{CmdSetAutoReplace,                      0}, /* 115 */
       
   308 	{CmdCloneVehicle,                        0}, /* 116 */
       
   309 	{CmdMassStartStopVehicle,                0}, /* 117 */
       
   310 	{CmdDepotSellAllVehicles,                0}, /* 118 */
       
   311 	{CmdDepotMassAutoReplace,                0}, /* 119 */
       
   312 };
       
   313 
       
   314 /* This function range-checks a cmd, and checks if the cmd is not NULL */
       
   315 bool IsValidCommand(uint cmd)
       
   316 {
       
   317 	cmd &= 0xFF;
       
   318 
       
   319 	return
       
   320 		cmd < lengthof(_command_proc_table) &&
       
   321 		_command_proc_table[cmd].proc != NULL;
       
   322 }
       
   323 
       
   324 byte GetCommandFlags(uint cmd)
       
   325 {
       
   326 	return _command_proc_table[cmd & 0xFF].flags;
       
   327 }
       
   328 
       
   329 
       
   330 static int _docommand_recursive;
       
   331 
       
   332 int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
       
   333 {
       
   334 	int32 res;
       
   335 	CommandProc *proc;
       
   336 
       
   337 	/* Do not even think about executing out-of-bounds tile-commands */
       
   338 	if (tile >= MapSize()) {
       
   339 		_cmd_text = NULL;
       
   340 		return CMD_ERROR;
       
   341 	}
       
   342 
       
   343 	proc = _command_proc_table[procc].proc;
       
   344 
       
   345 	if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
       
   346 
       
   347 	_docommand_recursive++;
       
   348 
       
   349 	// only execute the test call if it's toplevel, or we're not execing.
       
   350 	if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
       
   351 		res = proc(tile, flags & ~DC_EXEC, p1, p2);
       
   352 		if (CmdFailed(res)) {
       
   353 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
       
   354 			goto error;
       
   355 		}
       
   356 
       
   357 		if (_docommand_recursive == 1 &&
       
   358 				!(flags & DC_QUERY_COST) &&
       
   359 				res != 0 &&
       
   360 				!CheckPlayerHasMoney(res)) {
       
   361 			goto error;
       
   362 		}
       
   363 
       
   364 		if (!(flags & DC_EXEC)) {
       
   365 			_docommand_recursive--;
       
   366 			_cmd_text = NULL;
       
   367 			return res;
       
   368 		}
       
   369 	}
       
   370 
       
   371 	/* Execute the command here. All cost-relevant functions set the expenses type
       
   372 	 * themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */
       
   373 	res = proc(tile, flags, p1, p2);
       
   374 	if (CmdFailed(res)) {
       
   375 		if (res & 0xFFFF) _error_message = res & 0xFFFF;
       
   376 error:
       
   377 		_docommand_recursive--;
       
   378 		_cmd_text = NULL;
       
   379 		return CMD_ERROR;
       
   380 	}
       
   381 
       
   382 	// if toplevel, subtract the money.
       
   383 	if (--_docommand_recursive == 0) {
       
   384 		SubtractMoneyFromPlayer(res);
       
   385 		// XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player
       
   386 		if (tile != 0 && IsValidPlayer(_current_player)) {
       
   387 			GetPlayer(_current_player)->last_build_coordinate = tile;
       
   388 		}
       
   389 	}
       
   390 
       
   391 	_cmd_text = NULL;
       
   392 	return res;
       
   393 }
       
   394 
       
   395 int32 GetAvailableMoneyForCommand(void)
       
   396 {
       
   397 	PlayerID pid = _current_player;
       
   398 	if (!IsValidPlayer(pid)) return 0x7FFFFFFF; // max int
       
   399 	return GetPlayer(pid)->player_money;
       
   400 }
       
   401 
       
   402 // toplevel network safe docommand function for the current player. must not be called recursively.
       
   403 // the callback is called when the command succeeded or failed.
       
   404 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
       
   405 {
       
   406 	int32 res = 0,res2;
       
   407 	CommandProc *proc;
       
   408 	uint32 flags;
       
   409 	bool notest;
       
   410 	StringID error_part1;
       
   411 
       
   412 	int x = TileX(tile) * TILE_SIZE;
       
   413 	int y = TileY(tile) * TILE_SIZE;
       
   414 
       
   415 	/* Do not even think about executing out-of-bounds tile-commands */
       
   416 	if (tile >= MapSize()) {
       
   417 		_cmd_text = NULL;
       
   418 		return false;
       
   419 	}
       
   420 
       
   421 	assert(_docommand_recursive == 0);
       
   422 
       
   423 	_error_message = INVALID_STRING_ID;
       
   424 	error_part1 = GB(cmd, 16, 16);
       
   425 	_additional_cash_required = 0;
       
   426 
       
   427 	/** Spectator has no rights except for the (dedicated) server which
       
   428 	 * is/can be a spectator but as the server it can do anything */
       
   429 	if (_current_player == PLAYER_SPECTATOR && !_network_server) {
       
   430 		ShowErrorMessage(_error_message, error_part1, x, y);
       
   431 		_cmd_text = NULL;
       
   432 		return false;
       
   433 	}
       
   434 
       
   435 	flags = 0;
       
   436 	if (cmd & CMD_AUTO) flags |= DC_AUTO;
       
   437 	if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER;
       
   438 
       
   439 	// get pointer to command handler
       
   440 	assert((cmd & 0xFF) < lengthof(_command_proc_table));
       
   441 	proc = _command_proc_table[cmd & 0xFF].proc;
       
   442 	if (proc == NULL) {
       
   443 		_cmd_text = NULL;
       
   444 		return false;
       
   445 	}
       
   446 
       
   447 	// Some commands have a different output in dryrun than the realrun
       
   448 	//  e.g.: if you demolish a whole town, the dryrun would say okay.
       
   449 	//  but by really destroying, your rating drops and at a certain point
       
   450 	//  it will fail. so res and res2 are different
       
   451 	// CMD_REMOVE_ROAD: This command has special local authority
       
   452 	// restrictions which may cause the test run to fail (the previous
       
   453 	// road fragments still stay there and the town won't let you
       
   454 	// disconnect the road system), but the exec will succeed and this
       
   455 	// fact will trigger an assertion failure. --pasky
       
   456 	notest =
       
   457 		(cmd & 0xFF) == CMD_CLEAR_AREA ||
       
   458 		(cmd & 0xFF) == CMD_CONVERT_RAIL ||
       
   459 		(cmd & 0xFF) == CMD_LEVEL_LAND ||
       
   460 		(cmd & 0xFF) == CMD_REMOVE_ROAD ||
       
   461 		(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
       
   462 
       
   463 	_docommand_recursive = 1;
       
   464 
       
   465 	// cost estimation only?
       
   466 	if (!IsGeneratingWorld() &&
       
   467 			_shift_pressed &&
       
   468 			IsLocalPlayer() &&
       
   469 			!(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) &&
       
   470 			(cmd & 0xFF) != CMD_PAUSE) {
       
   471 		// estimate the cost.
       
   472 		res = proc(tile, flags, p1, p2);
       
   473 		if (CmdFailed(res)) {
       
   474 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
       
   475 			ShowErrorMessage(_error_message, error_part1, x, y);
       
   476 		} else {
       
   477 			ShowEstimatedCostOrIncome(res, x, y);
       
   478 		}
       
   479 
       
   480 		_docommand_recursive = 0;
       
   481 		_cmd_text = NULL;
       
   482 		return false;
       
   483 	}
       
   484 
       
   485 
       
   486 	if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
       
   487 		// first test if the command can be executed.
       
   488 		res = proc(tile, flags, p1, p2);
       
   489 		if (CmdFailed(res)) {
       
   490 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
       
   491 			goto show_error;
       
   492 		}
       
   493 		// no money? Only check if notest is off
       
   494 		if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
       
   495 	}
       
   496 
       
   497 #ifdef ENABLE_NETWORK
       
   498 	/** If we are in network, and the command is not from the network
       
   499 	 * send it to the command-queue and abort execution
       
   500 	 * If we are a dedicated server temporarily switch local player, otherwise
       
   501 	 * the other parties won't be able to execute our command and will desync.
       
   502 	 * We also need to do this if the server's company has gone bankrupt
       
   503 	 * @todo Rewrite (dedicated) server to something more than a dirty hack!
       
   504 	 */
       
   505 	if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
       
   506 		PlayerID pbck = _local_player;
       
   507 		if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = 0;
       
   508 		NetworkSend_Command(tile, p1, p2, cmd, callback);
       
   509 		if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
       
   510 		_docommand_recursive = 0;
       
   511 		_cmd_text = NULL;
       
   512 		return true;
       
   513 	}
       
   514 #endif /* ENABLE_NETWORK */
       
   515 
       
   516 	// update last build coordinate of player.
       
   517 	if (tile != 0 && IsValidPlayer(_current_player)) {
       
   518 		GetPlayer(_current_player)->last_build_coordinate = tile;
       
   519 	}
       
   520 
       
   521 	/* Actually try and execute the command. If no cost-type is given
       
   522 	 * use the construction one */
       
   523 	_yearly_expenses_type = EXPENSES_CONSTRUCTION;
       
   524 	res2 = proc(tile, flags | DC_EXEC, p1, p2);
       
   525 
       
   526 	// If notest is on, it means the result of the test can be different than
       
   527 	//   the real command.. so ignore the test
       
   528 	if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
       
   529 		assert(res == res2); // sanity check
       
   530 	} else {
       
   531 		if (CmdFailed(res2)) {
       
   532 			if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
       
   533 			goto show_error;
       
   534 		}
       
   535 	}
       
   536 
       
   537 	SubtractMoneyFromPlayer(res2);
       
   538 
       
   539 	if (IsLocalPlayer() && _game_mode != GM_EDITOR) {
       
   540 		if (res2 != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
       
   541 		if (_additional_cash_required) {
       
   542 			SetDParam(0, _additional_cash_required);
       
   543 			ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x,y);
       
   544 			if (res2 == 0) goto callb_err;
       
   545 		}
       
   546 	}
       
   547 
       
   548 	_docommand_recursive = 0;
       
   549 
       
   550 	if (callback) callback(true, tile, p1, p2);
       
   551 	_cmd_text = NULL;
       
   552 	return true;
       
   553 
       
   554 show_error:
       
   555 	// show error message if the command fails?
       
   556 	if (IsLocalPlayer() && error_part1 != 0) {
       
   557 		ShowErrorMessage(_error_message, error_part1, x,y);
       
   558 	}
       
   559 
       
   560 callb_err:
       
   561 	_docommand_recursive = 0;
       
   562 
       
   563 	if (callback) callback(false, tile, p1, p2);
       
   564 	_cmd_text = NULL;
       
   565 	return false;
       
   566 }