Fix: Don't send unused tile field over the network (#10507)

This commit is contained in:
dP 2023-02-25 01:50:11 +04:00 committed by GitHub
parent 9b3326e3fd
commit c73b88ddca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 60 additions and 78 deletions

View File

@ -97,11 +97,10 @@ ScriptInfo *AIInstance::FindLibrary(const char *library, int version)
* DoCommand callback function for all commands executed by AIs.
* @param cmd cmd as given to DoCommandPInternal.
* @param result The result of the command.
* @param tile The tile on which the command was executed.
* @param data Command data as given to Command<>::Post.
* @param result_data Additional returned data from the command.
*/
void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data)
void CcAI(Commands cmd, const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data)
{
/*
* The company might not exist anymore. Check for this.
@ -112,7 +111,7 @@ void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const Command
const Company *c = Company::GetIfValid(_current_company);
if (c == nullptr || c->ai_instance == nullptr) return;
if (c->ai_instance->DoCommandCallback(result, tile, data, std::move(result_data), cmd)) {
if (c->ai_instance->DoCommandCallback(result, data, std::move(result_data), cmd)) {
c->ai_instance->Continue();
}
}

View File

@ -37,7 +37,7 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID);
*/
#define return_cmd_error(errcode) return CommandCost(errcode);
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, TileIndex location, const CommandDataBuffer &cmd_data);
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data);
bool IsValidCommand(Commands cmd);
CommandFlags GetCommandFlags(Commands cmd);
@ -215,20 +215,13 @@ public:
* @param err_message Message prefix to show on error
* @param callback A callback function to call after the command is finished
* @param my_cmd indicator if the command is from a company or server (to display error messages for a user)
* @param location Tile location for user feedback.
* @param args Parameters for the command
* @return \c true if the command succeeded, else \c false.
*/
template <typename Tcallback>
static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, TileIndex location, std::tuple<Targs...> args)
static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, std::tuple<Targs...> args)
{
if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, decltype(args)>>) {
/* Do not even think about executing out-of-bounds tile-commands. */
TileIndex tile = std::get<0>(args);
if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && (GetCommandFlags<Tcmd>() & CMD_ALL_TILES) == 0))) return false;
}
return InternalPost(err_message, callback, my_cmd, true, location, std::move(args));
return InternalPost(err_message, callback, my_cmd, true, std::move(args));
}
/**
@ -242,12 +235,7 @@ public:
{
auto args_tuple = std::forward_as_tuple(args...);
TileIndex tile{};
if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, decltype(args_tuple)>>) {
tile = std::get<0>(args_tuple);
}
::NetworkSendCommand(Tcmd, err_message, nullptr, _current_company, tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args_tuple));
::NetworkSendCommand(Tcmd, err_message, nullptr, _current_company, EndianBufferWriter<CommandDataBuffer>::FromValue(args_tuple));
}
/**
@ -324,9 +312,9 @@ protected:
} else if constexpr (std::is_same_v<Tcallback, CommandCallbackData>) {
/* Generic callback that takes packed arguments as a buffer. */
if constexpr (std::is_same_v<Tret, CommandCost>) {
callback(Tcmd, ExtractCommandCost(res), tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args), {});
callback(Tcmd, ExtractCommandCost(res), EndianBufferWriter<CommandDataBuffer>::FromValue(args), {});
} else {
callback(Tcmd, ExtractCommandCost(res), tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args), EndianBufferWriter<CommandDataBuffer>::FromValue(RemoveFirstTupleElement(res)));
callback(Tcmd, ExtractCommandCost(res), EndianBufferWriter<CommandDataBuffer>::FromValue(args), EndianBufferWriter<CommandDataBuffer>::FromValue(RemoveFirstTupleElement(res)));
}
} else if constexpr (!std::is_same_v<Tret, CommandCost> && std::is_same_v<Tcallback *, typename CommandTraits<Tcmd>::RetCallbackProc>) {
std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res));
@ -405,7 +393,7 @@ protected:
/* If we are in network, and the command is not from the network
* send it to the command-queue and abort execution. */
if (send_net) {
::NetworkSendCommand(Tcmd, err_message, callback, _current_company, tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args));
::NetworkSendCommand(Tcmd, err_message, callback, _current_company, EndianBufferWriter<CommandDataBuffer>::FromValue(args));
cur_company.Restore();
/* Don't return anything special here; no error, no costs.
@ -446,8 +434,13 @@ protected:
template <Commands Tcmd, typename Tret, typename... Targs>
struct CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), false> : CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), true>
{
/* Import Post overloads from our base class. */
using CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), true>::Post;
/* Do not allow Post without explicit location. */
static inline bool Post(StringID err_message, Targs... args) = delete;
template <typename Tcallback>
static inline bool Post(Tcallback *callback, Targs... args) = delete;
static inline bool Post(Targs... args) = delete;
template <typename Tcallback>
static bool Post(StringID err_message, Tcallback *callback, Targs... args) = delete;
/**
* Shortcut for Post when not using a callback.
@ -476,7 +469,6 @@ struct CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), false> : CommandHel
* commands that don't take a TileIndex by themselves.
* @param err_message Message prefix to show on error
* @param callback A callback function to call after the command is finished
* @param location Tile location for user feedback.
* @param args Parameters for the command
* @return \c true if the command succeeded, else \c false.
*/
@ -492,6 +484,6 @@ struct CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), false> : CommandHel
#endif
template <Commands Tcmd>
using Command = CommandHelper<Tcmd, typename CommandTraits<Tcmd>::ProcType, std::is_same_v<TileIndex, std::tuple_element_t<0, typename CommandTraits<Tcmd>::Args>>>;
using Command = CommandHelper<Tcmd, typename CommandTraits<Tcmd>::ProcType, (GetCommandFlags<Tcmd>() & CMD_LOCATION) == 0>;
#endif /* COMMAND_FUNC_H */

View File

@ -388,6 +388,7 @@ enum CommandFlags {
CMD_DEITY = 0x100, ///< the command may be executed by COMPANY_DEITY
CMD_STR_CTRL = 0x200, ///< the command's string may contain control strings
CMD_NO_EST = 0x400, ///< the command is never estimated.
CMD_LOCATION = 0x800, ///< the command has implicit location argument.
};
DECLARE_ENUM_AS_BIT_SET(CommandFlags)
@ -479,6 +480,6 @@ typedef void CommandCallback(Commands cmd, const CommandCost &result, TileIndex
* @param result_data Additional returned data from the command
* @see CommandProc
*/
typedef void CommandCallbackData(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data);
typedef void CommandCallbackData(Commands cmd, const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data);
#endif /* COMMAND_TYPE_H */

View File

@ -84,13 +84,12 @@ void GameInstance::Died()
* DoCommand callback function for all commands executed by Game Scripts.
* @param cmd cmd as given to DoCommandPInternal.
* @param result The result of the command.
* @param tile The tile on which the command was executed.
* @param data Command data as given to Command<>::Post.
* @param result_data Additional returned data from the command.
*/
void CcGame(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data)
void CcGame(Commands cmd, const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data)
{
if (Game::GetGameInstance()->DoCommandCallback(result, tile, data, std::move(result_data), cmd)) {
if (Game::GetGameInstance()->DoCommandCallback(result, data, std::move(result_data), cmd)) {
Game::GetGameInstance()->Continue();
}
}

View File

@ -881,7 +881,7 @@ public:
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP);
GroupID new_g = id_g >= this->groups.size() ? NEW_GROUP : this->groups[id_g]->index;
Command<CMD_ADD_VEHICLE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE, new_g == NEW_GROUP ? CcAddVehicleNewGroup : nullptr, 0, new_g, vindex, _ctrl_pressed || this->grouping == GB_SHARED_ORDERS);
Command<CMD_ADD_VEHICLE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE, new_g == NEW_GROUP ? CcAddVehicleNewGroup : nullptr, new_g, vindex, _ctrl_pressed || this->grouping == GB_SHARED_ORDERS);
break;
}

View File

@ -261,17 +261,15 @@ static size_t FindCallbackIndex(CommandCallback *callback)
* @param err_message Message prefix to show on error
* @param callback A callback function to call after the command is finished
* @param company The company that wants to send the command
* @param location Location of the command (e.g. for error message position)
* @param cmd_data The command proc arguments.
*/
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, TileIndex location, const CommandDataBuffer &cmd_data)
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data)
{
CommandPacket c;
c.company = company;
c.cmd = cmd;
c.err_msg = err_message;
c.callback = callback;
c.tile = location;
c.data = cmd_data;
if (_network_server) {
@ -429,7 +427,6 @@ const char *NetworkGameSocketHandler::ReceiveCommand(Packet *p, CommandPacket *c
if (!IsValidCommand(cp->cmd)) return "invalid command";
if (GetCommandFlags(cp->cmd) & CMD_OFFLINE) return "single-player only command";
cp->err_msg = p->Recv_uint16();
cp->tile = p->Recv_uint32();
cp->data = _cmd_dispatch[cp->cmd].Sanitize(p->Recv_buffer());
byte callback = p->Recv_uint8();
@ -449,7 +446,6 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp)
p->Send_uint8(cp->company);
p->Send_uint16(cp->cmd);
p->Send_uint16(cp->err_msg);
p->Send_uint32(cp->tile);
p->Send_buffer(cp->data);
size_t callback = FindCallbackIndex(cp->callback);
@ -540,5 +536,5 @@ template <Commands Tcmd, size_t Tcb>
void UnpackNetworkCommand(const CommandPacket* cp)
{
auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp->data);
Command<Tcmd>::PostFromNet(cp->err_msg, std::get<Tcb>(_callback_tuple), cp->my_cmd, cp->tile, args);
Command<Tcmd>::PostFromNet(cp->err_msg, std::get<Tcb>(_callback_tuple), cp->my_cmd, args);
}

View File

@ -108,7 +108,7 @@ void UpdateNetworkGameWindow();
*/
struct CommandPacket {
/** Make sure the pointer is nullptr. */
CommandPacket() : next(nullptr), company(INVALID_COMPANY), frame(0), my_cmd(false), tile(0) {}
CommandPacket() : next(nullptr), company(INVALID_COMPANY), frame(0), my_cmd(false) {}
CommandPacket *next; ///< the next command packet (if in queue)
CompanyID company; ///< company that is executing the command
uint32 frame; ///< the frame in which this packet is executed
@ -117,7 +117,6 @@ struct CommandPacket {
Commands cmd; ///< command being executed.
StringID err_msg; ///< string ID of error message to use.
CommandCallback *callback; ///< any callback function executed upon successful completion of the command.
TileIndex tile; ///< location of the command (for e.g. error message or effect display).
CommandDataBuffer data; ///< command parameters.
};

View File

@ -23,13 +23,13 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve
CommandCost CmdMoveOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID moving_order, VehicleOrderID target_order);
CommandCost CmdClearOrderBackup(DoCommandFlag flags, TileIndex tile, ClientID user_id);
DEF_CMD_TRAIT(CMD_MODIFY_ORDER, CmdModifyOrder, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_SKIP_TO_ORDER, CmdSkipToOrder, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_DELETE_ORDER, CmdDeleteOrder, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_INSERT_ORDER, CmdInsertOrder, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_ORDER_REFIT, CmdOrderRefit, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CLONE_ORDER, CmdCloneOrder, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_MOVE_ORDER, CmdMoveOrder, 0, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_MODIFY_ORDER, CmdModifyOrder, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_SKIP_TO_ORDER, CmdSkipToOrder, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_DELETE_ORDER, CmdDeleteOrder, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_INSERT_ORDER, CmdInsertOrder, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_ORDER_REFIT, CmdOrderRefit, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CLONE_ORDER, CmdCloneOrder, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_MOVE_ORDER, CmdMoveOrder, CMD_LOCATION, CMDT_ROUTE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CLEAR_ORDER_BACKUP, CmdClearOrderBackup, CMD_CLIENT_ID, CMDT_SERVER_SETTING)
template <typename Tcont, typename Titer>

View File

@ -22,6 +22,6 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin
CommandCost CmdTurnRoadVeh(DoCommandFlag flags, VehicleID veh_id);
DEF_CMD_TRAIT(CMD_TURN_ROADVEH, CmdTurnRoadVeh, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_TURN_ROADVEH, CmdTurnRoadVeh, CMD_LOCATION, CMDT_VEHICLE_MANAGEMENT)
#endif /* ROADVEH_CMD_H */

View File

@ -82,20 +82,18 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return GetStorage()->mode_instance;
}
/* static */ void ScriptObject::SetLastCommand(TileIndex tile, const CommandDataBuffer &data, Commands cmd)
/* static */ void ScriptObject::SetLastCommand(const CommandDataBuffer &data, Commands cmd)
{
ScriptStorage *s = GetStorage();
Debug(script, 6, "SetLastCommand company={:02d} tile={:06x} cmd={} data={}", s->root_company, tile, cmd, FormatArrayAsHex(data));
s->last_tile = tile;
Debug(script, 6, "SetLastCommand company={:02d} cmd={} data={}", s->root_company, cmd, FormatArrayAsHex(data));
s->last_data = data;
s->last_cmd = cmd;
}
/* static */ bool ScriptObject::CheckLastCommand(TileIndex tile, const CommandDataBuffer &data, Commands cmd)
/* static */ bool ScriptObject::CheckLastCommand(const CommandDataBuffer &data, Commands cmd)
{
ScriptStorage *s = GetStorage();
Debug(script, 6, "CheckLastCommand company={:02d} tile={:06x} cmd={} data={}", s->root_company, tile, cmd, FormatArrayAsHex(data));
if (s->last_tile != tile) return false;
Debug(script, 6, "CheckLastCommand company={:02d} cmd={} data={}", s->root_company, cmd, FormatArrayAsHex(data));
if (s->last_cmd != cmd) return false;
if (s->last_data != data) return false;
return true;

View File

@ -118,12 +118,12 @@ protected:
/**
* Store the latest command executed by the script.
*/
static void SetLastCommand(TileIndex tile, const CommandDataBuffer &data, Commands cmd);
static void SetLastCommand(const CommandDataBuffer &data, Commands cmd);
/**
* Check if it's the latest command executed by the script.
*/
static bool CheckLastCommand(TileIndex tile, const CommandDataBuffer &data, Commands cmd);
static bool CheckLastCommand(const CommandDataBuffer &data, Commands cmd);
/**
* Sets the DoCommand costs counter to a value.
@ -354,7 +354,7 @@ bool ScriptObject::ScriptDoCommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...)>
if constexpr ((::GetCommandFlags<Tcmd>() & CMD_CLIENT_ID) != 0) ScriptObjectInternal::SetClientIds(args, std::index_sequence_for<Targs...>{});
/* Store the command for command callback validation. */
if (!estimate_only && networking) ScriptObject::SetLastCommand(tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args), Tcmd);
if (!estimate_only && networking) ScriptObject::SetLastCommand(EndianBufferWriter<CommandDataBuffer>::FromValue(args), Tcmd);
/* Try to perform the command. */
Tret res = ::Command<Tcmd>::Unsafe((StringID)0, networking ? ScriptObject::GetDoCommandCallback() : nullptr, false, estimate_only, tile, args);

View File

@ -744,11 +744,11 @@ SQInteger ScriptInstance::GetOpsTillSuspend()
return this->engine->GetOpsTillSuspend();
}
bool ScriptInstance::DoCommandCallback(const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data, Commands cmd)
bool ScriptInstance::DoCommandCallback(const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data, Commands cmd)
{
ScriptObject::ActiveInstance active(this);
if (!ScriptObject::CheckLastCommand(tile, data, cmd)) {
if (!ScriptObject::CheckLastCommand(data, cmd)) {
Debug(script, 1, "DoCommandCallback terminating a script, last command does not match expected command");
return false;
}
@ -763,7 +763,7 @@ bool ScriptInstance::DoCommandCallback(const CommandCost &result, TileIndex tile
ScriptObject::SetLastCost(result.GetCost());
}
ScriptObject::SetLastCommand(INVALID_TILE, {}, CMD_END);
ScriptObject::SetLastCommand({}, CMD_END);
return true;
}

View File

@ -217,7 +217,7 @@ public:
* @param cmd cmd as given to DoCommandPInternal.
* @return true if we handled result.
*/
bool DoCommandCallback(const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data, Commands cmd);
bool DoCommandCallback(const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data, Commands cmd);
/**
* Insert an event for this script.

View File

@ -44,7 +44,6 @@ private:
uint last_error; ///< The last error of the command.
bool last_command_res; ///< The last result of the command.
TileIndex last_tile; ///< The last tile passed to a command.
CommandDataBuffer last_data; ///< The last data passed to a command.
Commands last_cmd; ///< The last cmd passed to a command.
CommandDataBuffer last_cmd_ret; ///< The extra data returned by the last command.
@ -69,7 +68,6 @@ public:
last_cost (0),
last_error (STR_NULL),
last_command_res (true),
last_tile (INVALID_TILE),
last_cmd (CMD_END),
/* calback_value (can't be set) */
road_type (INVALID_ROADTYPE),

View File

@ -28,7 +28,7 @@ CommandCost CmdDeleteTown(DoCommandFlag flags, TownID town_id);
DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CMD_DEITY | CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION) // founding random town can fail only in exec run
DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CMD_DEITY | CMD_SERVER, CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_DO_TOWN_ACTION, CmdDoTownAction, 0, CMDT_LANDSCAPE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_DO_TOWN_ACTION, CmdDoTownAction, CMD_LOCATION, CMDT_LANDSCAPE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_TOWN_CARGO_GOAL, CmdTownCargoGoal, CMD_DEITY, CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_TOWN_GROWTH_RATE, CmdTownGrowthRate, CMD_DEITY, CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_TOWN_RATING, CmdTownRating, CMD_DEITY, CMDT_OTHER_MANAGEMENT)

View File

@ -21,9 +21,9 @@ CommandCost CmdMoveRailVehicle(DoCommandFlag flags, VehicleID src_veh, VehicleID
CommandCost CmdForceTrainProceed(DoCommandFlag flags, VehicleID veh_id);
CommandCost CmdReverseTrainDirection(DoCommandFlag flags, VehicleID veh_id, bool reverse_single_veh);
DEF_CMD_TRAIT(CMD_MOVE_RAIL_VEHICLE, CmdMoveRailVehicle, 0, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_FORCE_TRAIN_PROCEED, CmdForceTrainProceed, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_REVERSE_TRAIN_DIRECTION, CmdReverseTrainDirection, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_MOVE_RAIL_VEHICLE, CmdMoveRailVehicle, CMD_LOCATION, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_FORCE_TRAIN_PROCEED, CmdForceTrainProceed, CMD_LOCATION, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_REVERSE_TRAIN_DIRECTION, CmdReverseTrainDirection, CMD_LOCATION, CMDT_VEHICLE_MANAGEMENT)
void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16, CargoArray, TileIndex tile, EngineID, bool, CargoID, ClientID);

View File

@ -44,7 +44,7 @@ void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id,
if (found != nullptr) {
found = found->Last();
/* put the new wagon at the end of the loco. */
Command<CMD_MOVE_RAIL_VEHICLE>::Post(new_veh_id, found->index, false);
Command<CMD_MOVE_RAIL_VEHICLE>::Post(found->tile, new_veh_id, found->index, false);
InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
}
}

View File

@ -28,17 +28,17 @@ CommandCost CmdMassStartStopVehicle(DoCommandFlag flags, TileIndex tile, bool do
CommandCost CmdDepotSellAllVehicles(DoCommandFlag flags, TileIndex tile, VehicleType vehicle_type);
CommandCost CmdDepotMassAutoReplace(DoCommandFlag flags, TileIndex tile, VehicleType vehicle_type);
DEF_CMD_TRAIT(CMD_BUILD_VEHICLE, CmdBuildVehicle, CMD_CLIENT_ID, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_SELL_VEHICLE, CmdSellVehicle, CMD_CLIENT_ID, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_REFIT_VEHICLE, CmdRefitVehicle, 0, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_SEND_VEHICLE_TO_DEPOT, CmdSendVehicleToDepot, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CHANGE_SERVICE_INT, CmdChangeServiceInt, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_RENAME_VEHICLE, CmdRenameVehicle, 0, CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CLONE_VEHICLE, CmdCloneVehicle, CMD_NO_TEST, CMDT_VEHICLE_CONSTRUCTION) // NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost
DEF_CMD_TRAIT(CMD_START_STOP_VEHICLE, CmdStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_MASS_START_STOP, CmdMassStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_DEPOT_SELL_ALL_VEHICLES, CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_DEPOT_MASS_AUTOREPLACE, CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_BUILD_VEHICLE, CmdBuildVehicle, CMD_CLIENT_ID, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_SELL_VEHICLE, CmdSellVehicle, CMD_CLIENT_ID | CMD_LOCATION, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_REFIT_VEHICLE, CmdRefitVehicle, CMD_LOCATION, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_SEND_VEHICLE_TO_DEPOT, CmdSendVehicleToDepot, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CHANGE_SERVICE_INT, CmdChangeServiceInt, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_RENAME_VEHICLE, CmdRenameVehicle, 0, CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_CLONE_VEHICLE, CmdCloneVehicle, CMD_NO_TEST, CMDT_VEHICLE_CONSTRUCTION) // NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost
DEF_CMD_TRAIT(CMD_START_STOP_VEHICLE, CmdStartStopVehicle, CMD_LOCATION, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_MASS_START_STOP, CmdMassStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT)
DEF_CMD_TRAIT(CMD_DEPOT_SELL_ALL_VEHICLES, CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_DEPOT_MASS_AUTOREPLACE, CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION)
void CcBuildPrimaryVehicle(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16, CargoArray);
void CcStartStopVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id, bool);