Add third DoCommand parameter p3

pull/199/head
Jonathan G Rennison 4 years ago
parent 5c43de8ef8
commit bbbda0739b

@ -98,7 +98,7 @@ ScriptInfo *AIInstance::FindLibrary(const char *library, int version)
* @param p2 p2 as given to DoCommandPInternal.
* @param cmd cmd as given to DoCommandPInternal.
*/
void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
/*
* The company might not exist anymore. Check for this.
@ -109,7 +109,7 @@ void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint3
const Company *c = Company::GetIfValid(_current_company);
if (c == nullptr || c->ai_instance == nullptr) return;
if (c->ai_instance->DoCommandCallback(result, tile, p1, p2, cmd)) {
if (c->ai_instance->DoCommandCallback(result, tile, p1, p2, p3, cmd)) {
c->ai_instance->Continue();
}
}

@ -40,7 +40,7 @@ static void ShowBuildAirportPicker(Window *parent);
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout);
void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -60,7 +60,7 @@ static void PlaceAirport(TileIndex tile)
uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
p1 |= _selected_airport_layout << 8;
CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, 0, "" };
CommandContainer cmdcont = NewCommandContainerBasic(tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport);
ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE));
}

@ -59,7 +59,7 @@ typedef GUIList<BuildBridgeData> GUIBridgeList; ///< List of bridges, used in #B
* - p2 = (bit 15-16) - transport type.
* @param cmd unused
*/
void CcBuildBridge(const CommandCost &result, TileIndex end_tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildBridge(const CommandCost &result, TileIndex end_tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, end_tile);

@ -1707,7 +1707,7 @@ struct BuildVehicleWindow : Window {
}
};
void CcAddVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcAddVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -1720,7 +1720,7 @@ void CcAddVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, ui
}
}
void CcMoveNewVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcMoveNewVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

@ -88,7 +88,7 @@ CommandProc CmdPlantTree;
CommandProc CmdMoveRailVehicle;
CommandProcEx CmdBuildVehicle;
CommandProc CmdBuildVehicle;
CommandProc CmdSellVehicle;
CommandProc CmdRefitVehicle;
CommandProc CmdSendVehicleToDepot;
@ -524,6 +524,7 @@ struct CommandLogEntry {
uint32 p1;
uint32 p2;
uint32 cmd;
uint64 p3;
Date date;
DateFract date_fract;
uint8 tick_skip_counter;
@ -533,8 +534,8 @@ struct CommandLogEntry {
CommandLogEntry() { }
CommandLogEntry(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandLogEntryFlag log_flags)
: tile(tile), p1(p1), p2(p2), cmd(cmd), date(_date), date_fract(_date_fract), tick_skip_counter(_tick_skip_counter),
CommandLogEntry(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandLogEntryFlag log_flags)
: tile(tile), p1(p1), p2(p2), cmd(cmd), p3(p3), date(_date), date_fract(_date_fract), tick_skip_counter(_tick_skip_counter),
current_company(_current_company), local_company(_local_company), log_flags(log_flags) { }
};
@ -580,8 +581,13 @@ static void DumpSubCommandLog(char *&buffer, const char *last, const CommandLog
buffer += seprintf(buffer, last, "%c%c%c%c%c%c%c%c%c | ",
fc(CLEF_TWICE, '2'), fc(CLEF_SCRIPT, 'a'), fc(CLEF_BINARY, 'b'), fc(CLEF_MY_CMD, 'm'), fc(CLEF_ONLY_SENDING, 's'),
fc(CLEF_ESTIMATE_ONLY, 'e'), fc(CLEF_TEXT, 't'), fc(CLEF_GENERATING_WORLD, 'g'), fc(CLEF_CMD_FAILED, 'f'));
buffer += seprintf(buffer, last, " %7d x %7d, p1: 0x%08X, p2: 0x%08X, cc: %3u, lc: %3u, cmd: 0x%08X (%s)\n",
TileX(entry.tile), TileY(entry.tile), entry.p1, entry.p2, (uint) entry.current_company, (uint) entry.local_company, entry.cmd, GetCommandName(entry.cmd));
buffer += seprintf(buffer, last, " %7d x %7d, p1: 0x%08X, p2: 0x%08X, ",
TileX(entry.tile), TileY(entry.tile), entry.p1, entry.p2);
if (entry.p3 != 0) {
buffer += seprintf(buffer, last, "p3: 0x" OTTD_PRINTFHEX64PAD ", ", entry.p3);
}
buffer += seprintf(buffer, last, "cc: %3u, lc: %3u, cmd: 0x%08X (%s)\n",
(uint) entry.current_company, (uint) entry.local_company, entry.cmd, GetCommandName(entry.cmd));
}
}
@ -668,19 +674,6 @@ bool IsCommandAllowedWhilePaused(uint32 cmd)
static int _docommand_recursive = 0;
/**
* Shorthand for calling the long DoCommand with a container.
*
* @param container Container with (almost) all information
* @param flags Flags for the command and how to execute the command
* @see CommandProc
* @return the cost
*/
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
{
return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text.c_str(), container->binary_length);
}
struct cmd_text_info_dumper {
const char *CommandTextInfo(const char *text, uint32 binary_length)
{
@ -715,10 +708,10 @@ private:
* @see CommandProc
* @return the cost
*/
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text, uint32 binary_length)
CommandCost DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, DoCommandFlag flags, uint32 cmd, const char *text, uint32 binary_length)
{
SCOPE_INFO_FMT([=], "DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, flags: 0x%X, company: %s, cmd: 0x%X (%s)%s",
tile, TileX(tile), TileY(tile), p1, p2, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), cmd_text_info_dumper().CommandTextInfo(text, binary_length));
SCOPE_INFO_FMT([=], "DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, p3: " OTTD_PRINTFHEX64 ", flags: 0x%X, company: %s, cmd: 0x%X (%s)%s",
tile, TileX(tile), TileY(tile), p1, p2, p3, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), cmd_text_info_dumper().CommandTextInfo(text, binary_length));
CommandCost res;
@ -734,7 +727,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
if (_docommand_recursive == 1) _cleared_object_areas.clear();
SetTownRatingTestMode(true);
res = command.Execute(tile, flags & ~DC_EXEC, p1, p2, text, binary_length);
res = command.Execute(tile, flags & ~DC_EXEC, p1, p2, p3, text, binary_length);
SetTownRatingTestMode(false);
if (res.Failed()) {
goto error;
@ -756,7 +749,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
/* Execute the command here. All cost-relevant functions set the expenses type
* themselves to the cost object at some point */
if (_docommand_recursive == 1) _cleared_object_areas.clear();
res = command.Execute(tile, flags, p1, p2, text, binary_length);
res = command.Execute(tile, flags, p1, p2, p3, text, binary_length);
if (res.Failed()) {
error:
_docommand_recursive--;
@ -785,7 +778,7 @@ Money GetAvailableMoneyForCommand()
return Company::Get(company)->money;
}
static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandLogEntryFlag log_flags)
static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandLogEntryFlag log_flags)
{
if (res.Failed()) log_flags |= CLEF_CMD_FAILED;
if (_generating_world) log_flags |= CLEF_GENERATING_WORLD;
@ -795,7 +788,7 @@ static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32
if (_networking && cmd_log.count > 0) {
CommandLogEntry &current = cmd_log.log[(cmd_log.next - 1) % cmd_log.log.size()];
if (current.log_flags & CLEF_ONLY_SENDING && ((current.log_flags ^ log_flags) & ~(CLEF_SCRIPT | CLEF_MY_CMD)) == CLEF_ONLY_SENDING &&
current.tile == tile && current.p1 == p1 && current.p2 == p2 && ((current.cmd ^ cmd) & ~CMD_NETWORK_COMMAND) == 0 && current.date == _date &&
current.tile == tile && current.p1 == p1 && current.p2 == p2 && current.p3 == p3 && ((current.cmd ^ cmd) & ~CMD_NETWORK_COMMAND) == 0 && current.date == _date &&
current.date_fract == _date_fract && current.tick_skip_counter == _tick_skip_counter &&
current.current_company == _current_company && current.local_company == _local_company) {
current.log_flags |= log_flags | CLEF_TWICE;
@ -803,22 +796,11 @@ static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32
return;
}
}
cmd_log.log[cmd_log.next] = CommandLogEntry(tile, p1, p2, cmd, log_flags);
cmd_log.log[cmd_log.next] = CommandLogEntry(tile, p1, p2, p3, cmd, log_flags);
cmd_log.next = (cmd_log.next + 1) % cmd_log.log.size();
cmd_log.count++;
}
/**
* Shortcut for the long DoCommandP when having a container with the data.
* @param container the container with information.
* @param my_cmd indicator if the command is from a company or server (to display error messages for a user)
* @return true if the command succeeded, else false
*/
bool DoCommandP(const CommandContainer *container, bool my_cmd)
{
return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text.c_str(), my_cmd, container->binary_length);
}
/*!
* Toplevel network safe docommand function for the current company. Must not be called recursively.
* The callback is called when the command succeeded or failed. The parameters
@ -828,6 +810,7 @@ bool DoCommandP(const CommandContainer *container, bool my_cmd)
* @param tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc)
* @param p2 Additional data for the command (see #CommandProc)
* @param p3 Additional data for the command (see #CommandProc)
* @param cmd The command to execute (a CMD_* value)
* @param callback A callback function to call after the command is finished
* @param text The text to pass
@ -835,10 +818,10 @@ bool DoCommandP(const CommandContainer *container, bool my_cmd)
* @param binary_length The length of binary data in text
* @return \c true if the command succeeded, else \c false.
*/
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, uint32 binary_length)
bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, uint32 binary_length, bool my_cmd)
{
SCOPE_INFO_FMT([=], "DoCommandP: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, company: %s, cmd: 0x%X (%s), my_cmd: %d%s",
tile, TileX(tile), TileY(tile), p1, p2, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), my_cmd, cmd_text_info_dumper().CommandTextInfo(text, binary_length));
SCOPE_INFO_FMT([=], "DoCommandP: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, p3: 0x" OTTD_PRINTFHEX64 ", company: %s, cmd: 0x%X (%s), my_cmd: %d%s",
tile, TileX(tile), TileY(tile), p1, p2, p3, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), my_cmd, cmd_text_info_dumper().CommandTextInfo(text, binary_length));
/* Cost estimation is generally only done when the
* local user presses shift while doing something.
@ -866,7 +849,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac
/* Only set p2 when the command does not come from the network. */
if (!(cmd & CMD_NETWORK_COMMAND) && GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = CLIENT_ID_SERVER;
CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only, binary_length);
CommandCost res = DoCommandPInternal(tile, p1, p2, p3, cmd, callback, text, my_cmd, estimate_only, binary_length);
CommandLogEntryFlag log_flags;
log_flags = CLEF_NONE;
@ -875,7 +858,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac
if (only_sending) log_flags |= CLEF_ONLY_SENDING;
if (my_cmd) log_flags |= CLEF_MY_CMD;
if (binary_length > 0) log_flags |= CLEF_BINARY;
AppendCommandLogEntry(res, tile, p1, p2, cmd, log_flags);
AppendCommandLogEntry(res, tile, p1, p2, p3, cmd, log_flags);
if (res.Failed()) {
/* Only show the error when it's for us. */
@ -895,15 +878,15 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac
}
if (!estimate_only && !only_sending && callback != nullptr) {
callback(res, tile, p1, p2, cmd);
callback(res, tile, p1, p2, p3, cmd);
}
return res.Succeeded();
}
CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length)
CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length)
{
CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only, binary_length);
CommandCost res = DoCommandPInternal(tile, p1, p2, p3, cmd, callback, text, my_cmd, estimate_only, binary_length);
CommandLogEntryFlag log_flags;
log_flags = CLEF_SCRIPT;
@ -912,7 +895,7 @@ CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, C
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) log_flags |= CLEF_ONLY_SENDING;
if (my_cmd) log_flags |= CLEF_MY_CMD;
if (binary_length > 0) log_flags |= CLEF_BINARY;
AppendCommandLogEntry(res, tile, p1, p2, cmd, log_flags);
AppendCommandLogEntry(res, tile, p1, p2, p3, cmd, log_flags);
return res;
}
@ -930,6 +913,7 @@ CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, C
* @param tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc)
* @param p2 Additional data for the command (see #CommandProc)
* @param p3 Additional data for the command (see #CommandProc)
* @param cmd The command to execute (a CMD_* value)
* @param callback A callback function to call after the command is finished
* @param text The text to pass
@ -937,7 +921,7 @@ CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, C
* @param estimate_only whether to give only the estimate or also execute the command
* @return the command cost of this function.
*/
CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length)
CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length)
{
/* Prevent recursion; it gives a mess over the network */
assert(_docommand_recursive == 0);
@ -987,13 +971,13 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
_cleared_object_areas.clear();
SetTownRatingTestMode(true);
BasePersistentStorageArray::SwitchMode(PSM_ENTER_TESTMODE);
CommandCost res = command.Execute(tile, flags, p1, p2, text, binary_length);
CommandCost res = command.Execute(tile, flags, p1, p2, p3, text, binary_length);
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_TESTMODE);
SetTownRatingTestMode(false);
if (!random_state.Check()) {
std::string msg = stdstr_fmt("Random seed changed in test command: company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; cmd: %08x; \"%s\" %X (%s)",
(int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd));
std::string msg = stdstr_fmt("Random seed changed in test command: company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; p3: " OTTD_PRINTFHEX64PAD "; cmd: %08x; \"%s\" %X (%s)",
(int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd));
DEBUG(desync, 0, "msg: date{%08x; %02x; %02x}; %s", _date, _date_fract, _tick_skip_counter, msg.c_str());
LogDesyncMsg(std::move(msg));
}
@ -1011,8 +995,8 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
if (!_networking || _generating_world || (cmd & CMD_NETWORK_COMMAND) != 0) {
/* Log the failed command as well. Just to be able to be find
* causes of desyncs due to bad command test implementations. */
DEBUG(desync, 1, "cmdf: date{%08x; %02x; %02x}; company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; cmd: %08x; \"%s\" %X (%s)",
_date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd));
DEBUG(desync, 1, "cmdf: date{%08x; %02x; %02x}; company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; p3: " OTTD_PRINTFHEX64PAD "; cmd: %08x; \"%s\" %X (%s)",
_date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd));
}
cur_company.Restore();
return_dcpi(res);
@ -1023,7 +1007,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
* send it to the command-queue and abort execution
*/
if (_networking && !_generating_world && !(cmd & CMD_NETWORK_COMMAND)) {
NetworkSendCommand(tile, p1, p2, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company, binary_length);
NetworkSendCommand(tile, p1, p2, p3, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company, binary_length);
cur_company.Restore();
/* Don't return anything special here; no error, no costs.
@ -1032,14 +1016,14 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
* reset the storages as we've not executed the command. */
return_dcpi(CommandCost());
}
DEBUG(desync, 1, "cmd: date{%08x; %02x; %02x}; company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; cmd: %08x; \"%s\" %X (%s)",
_date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd));
DEBUG(desync, 1, "cmd: date{%08x; %02x; %02x}; company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; p3: " OTTD_PRINTFHEX64PAD "; cmd: %08x; \"%s\" %X (%s)",
_date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd));
/* Actually try and execute the command. If no cost-type is given
* use the construction one */
_cleared_object_areas.clear();
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND);
CommandCost res2 = command.Execute(tile, flags | DC_EXEC, p1, p2, text, binary_length);
CommandCost res2 = command.Execute(tile, flags | DC_EXEC, p1, p2, p3, text, binary_length);
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND);
if (cmd_id == CMD_COMPANY_CTRL) {

@ -32,16 +32,33 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID);
*/
#define return_cmd_error(errcode) return CommandCost(errcode);
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = nullptr, uint32 binary_length = 0);
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags);
CommandCost DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, DoCommandFlag flags, uint32 cmd, const char *text = nullptr, uint32 binary_length = 0);
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = nullptr, const char *text = nullptr, bool my_cmd = true, uint32 binary_length = 0);
bool DoCommandP(const CommandContainer *container, bool my_cmd = true);
inline CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = nullptr)
{
return DoCommandEx(tile, p1, p2, 0, flags, cmd, text, 0);
}
inline CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
{
return DoCommandEx(container->tile, container->p1, container->p2, container->p3, flags, container->cmd & CMD_ID_MASK, container->text.c_str(), container->binary_length);
}
bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, uint32 binary_length, bool my_cmd = true);
inline bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = nullptr, const char *text = nullptr, bool my_cmd = true)
{
return DoCommandPEx(tile, p1, p2, 0, cmd, callback, text, 0, my_cmd);
}
inline bool DoCommandP(const CommandContainer *container, bool my_cmd = true)
{
return DoCommandPEx(container->tile, container->p1, container->p2, container->p3, container->cmd, container->callback, container->text.c_str(), container->binary_length, my_cmd);
}
CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length);
CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length);
CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length);
CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, uint32 binary_length);
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company, uint32 binary_length);
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company, uint32 binary_length);
extern Money _additional_cash_required;

@ -568,7 +568,7 @@ enum CommandPauseLevel {
* @return The CommandCost of the command, which can be succeeded or failed.
*/
typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
typedef CommandCost CommandProcEx(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length);
typedef CommandCost CommandProcEx(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length);
/**
* Define a command with the flags which belongs to it.
@ -590,9 +590,9 @@ struct Command {
Command(CommandProcEx *procex, const char *name, CommandFlags flags, CommandType type)
: procex(procex), name(name), flags(flags | CMD_PROCEX), type(type) {}
inline CommandCost Execute(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length) const {
inline CommandCost Execute(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) const {
if (this->flags & CMD_PROCEX) {
return this->procex(tile, flags, p1, p2, text, binary_length);
return this->procex(tile, flags, p1, p2, p3, text, binary_length);
} else {
return this->proc(tile, flags, p1, p2, text);
}
@ -609,10 +609,11 @@ struct Command {
* @param result The result of the executed command
* @param tile The tile of the command action
* @param p1 Additional data of the command
* @param p1 Additional data of the command
* @param p2 Additional data of the command
* @param p3 Additional data of the command
* @see CommandProc
*/
typedef void CommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd);
typedef void CommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd);
#define MAX_CMD_TEXT_LENGTH 32000
@ -624,9 +625,15 @@ struct CommandContainer {
uint32 p1; ///< parameter p1.
uint32 p2; ///< parameter p2.
uint32 cmd; ///< command being executed.
uint64 p3; ///< parameter p3. (here for alignment)
CommandCallback *callback; ///< any callback function executed upon successful completion of the command.
uint32 binary_length; ///< in case text contains binary data, this describes its length.
std::string text; ///< possible text sent for name changes etc.
};
inline CommandContainer NewCommandContainerBasic(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = nullptr)
{
return { tile, p1, p2, cmd, 0, callback, 0, {} };
}
#endif /* COMMAND_TYPE_H */

@ -119,7 +119,7 @@ extern void DepotSortList(VehicleList *list);
* @param p2 unused
* @param cmd unused
*/
void CcCloneVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcCloneVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

@ -38,7 +38,7 @@ static void ShowBuildDocksDepotPicker(Window *parent);
static Axis _ship_depot_direction;
void CcBuildDocks(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildDocks(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -46,7 +46,7 @@ void CcBuildDocks(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
}
void CcPlaySound_SPLAT_WATER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcPlaySound_SPLAT_WATER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_02_SPLAT_WATER, tile);
}
@ -196,7 +196,7 @@ struct BuildDocksToolbarWindow : Window {
uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join
/* tile is always the land tile, so need to evaluate _thd.pos */
CommandContainer cmdcont = { tile, _ctrl_pressed, p2, CMD_BUILD_DOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_DOCK_HERE), CcBuildDocks, 0, "" };
CommandContainer cmdcont = NewCommandContainerBasic(tile, _ctrl_pressed, p2, CMD_BUILD_DOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_DOCK_HERE), CcBuildDocks);
/* Determine the watery part of the dock. */
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));

@ -85,11 +85,12 @@ void GameInstance::Died()
* @param tile The tile on which the command was executed.
* @param p1 p1 as given to DoCommandPInternal.
* @param p2 p2 as given to DoCommandPInternal.
* @param p3 p3 as given to DoCommandPInternal.
* @param cmd cmd as given to DoCommandPInternal.
*/
void CcGame(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcGame(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (Game::GetGameInstance()->DoCommandCallback(result, tile, p1, p2, cmd)) {
if (Game::GetGameInstance()->DoCommandCallback(result, tile, p1, p2, p3, cmd)) {
Game::GetGameInstance()->Continue();
}
}

@ -1212,7 +1212,7 @@ static inline VehicleGroupWindow *FindVehicleGroupWindow(VehicleType vt, Owner o
* @param cmd Unused.
* @see CmdCreateGroup
*/
void CcCreateGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcCreateGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
assert(p1 <= VEH_AIRCRAFT);
@ -1229,12 +1229,12 @@ void CcCreateGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32
* @param p2 Bit 0-19: Vehicle ID.
* @param cmd Unused.
*/
void CcAddVehicleNewGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcAddVehicleNewGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
assert(Vehicle::IsValidID(GB(p2, 0, 20)));
CcCreateGroup(result, 0, Vehicle::Get(GB(p2, 0, 20))->type, 0, cmd);
CcCreateGroup(result, 0, Vehicle::Get(GB(p2, 0, 20))->type, 0, 0, cmd);
}
/**

@ -222,7 +222,7 @@ void SortIndustryTypes()
* @param p2 Additional data of the #CMD_BUILD_INDUSTRY command.
* @param cmd Unused.
*/
void CcBuildIndustry(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildIndustry(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) return;

@ -48,7 +48,7 @@
#include "safeguards.h"
void CcGiveMoney(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcGiveMoney(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed() || !_settings_game.economy.give_money || !_networking) return;
@ -98,7 +98,7 @@ bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, HighLightStyl
}
void CcPlaySound_EXPLOSION(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcPlaySound_EXPLOSION(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_12_EXPLOSION, tile);
}

@ -901,8 +901,8 @@ void NetworkGameLoop()
while (f != nullptr && !feof(f)) {
if (_date == next_date && _date_fract == next_date_fract) {
if (cp != nullptr) {
NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text.c_str(), cp->company, cp->binary_length);
DEBUG(net, 0, "injecting: date{%08x; %02x; %02x}; %02x; %06x; %08x; %08x; %08x; \"%s\" (%x) (%s)", _date, _date_fract, _tick_skip_counter, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text.c_str(), cp->binary_length, GetCommandName(cp->cmd));
NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text.c_str(), cp->company, cp->binary_length);
DEBUG(net, 0, "injecting: date{%08x; %02x; %02x}; %02x; %06x; %08x; %08x; " OTTD_PRINTFHEX64PAD " %08x; \"%s\" (%x) (%s)", _date, _date_fract, _tick_skip_counter, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd, cp->text.c_str(), cp->binary_length, GetCommandName(cp->cmd));
cp.reset();
}
if (check_sync_state) {
@ -941,11 +941,12 @@ void NetworkGameLoop()
int company;
cp->text.resize(MAX_CMD_TEXT_LENGTH);
assert_compile(MAX_CMD_TEXT_LENGTH > 8192);
int ret = sscanf(p, "date{%x; %x; %x}; company: %x; tile: %x (%*u x %*u); p1: %x; p2: %x; cmd: %x; \"%8192[^\"]\"", &next_date, &next_date_fract, &next_tick_skip_counter, &company, &cp->tile, &cp->p1, &cp->p2, &cp->cmd, const_cast<char *>(cp->text.c_str()));
/* There are 9 pieces of data to read, however the last is a
int ret = sscanf(p, "date{%x; %x; %x}; company: %x; tile: %x (%*u x %*u); p1: %x; p2: %x; p3: " OTTD_PRINTFHEX64 "; cmd: %x; \"%8192[^\"]\"",
&next_date, &next_date_fract, &next_tick_skip_counter, &company, &cp->tile, &cp->p1, &cp->p2, &cp->p3, &cp->cmd, const_cast<char *>(cp->text.c_str()));
/* There are 10 pieces of data to read, however the last is a
* string that might or might not exist. Ignore it if that
* string misses because in 99% of the time it's not used. */
assert(ret == 9 || ret == 8);
assert(ret == 10 || ret == 9);
cp->company = (CompanyID)company;
cp->binary_length = 0;
} else if (strncmp(p, "join: ", 6) == 0) {
@ -959,6 +960,7 @@ void NetworkGameLoop()
cp->cmd = CMD_PAUSE;
cp->p1 = PM_PAUSED_NORMAL;
cp->p2 = 1;
cp->p3 = 0;
cp->callback = nullptr;
cp->binary_length = 0;
_ddc_fastforward = false;

@ -993,7 +993,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
* the server will give us a client-id and let us in */
_network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
ShowJoinStatusWindow();
NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, 0);
NetworkSendCommand(0, CCA_NEW, 0, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, 0);
}
} else {
/* take control over an existing company */

@ -137,13 +137,14 @@ static CommandQueue _local_execution_queue;
* @param tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc)
* @param p2 Additional data for the command (see #CommandProc)
* @param p3 Additional data for the command (see #CommandProc)
* @param cmd The command to execute (a CMD_* value)
* @param callback A callback function to call after the command is finished
* @param text The text to pass
* @param company The company that wants to send the command
* @param binary_length The quantity of binary data in text
*/
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company, uint32 binary_length)
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company, uint32 binary_length)
{
assert((cmd & CMD_FLAGS_MASK) == 0);
@ -152,6 +153,7 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comman
c.tile = tile;
c.p1 = p1;
c.p2 = p2;
c.p3 = p3;
c.cmd = cmd;
c.callback = callback;
@ -320,6 +322,7 @@ const char *NetworkGameSocketHandler::ReceiveCommand(Packet *p, CommandPacket *c
cp->p1 = p->Recv_uint32();
cp->p2 = p->Recv_uint32();
cp->p3 = p->Recv_uint64();
cp->tile = p->Recv_uint32();
cp->binary_length = p->Recv_uint32();
if (cp->binary_length == 0) {
@ -348,6 +351,7 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp)
p->Send_uint32(cp->cmd);
p->Send_uint32(cp->p1);
p->Send_uint32(cp->p2);
p->Send_uint64(cp->p3);
p->Send_uint32(cp->tile);
p->Send_uint32(cp->binary_length);
if (cp->binary_length == 0) {

@ -1244,7 +1244,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p
_settings_client.network.sync_freq = min<uint16>(_settings_client.network.sync_freq, 16);
// have the server and all clients run some sanity checks
NetworkSendCommand(0, 0, 0, CMD_DESYNC_CHECK, nullptr, nullptr, _local_company, 0);
NetworkSendCommand(0, 0, 0, 0, CMD_DESYNC_CHECK, nullptr, nullptr, _local_company, 0);
SendPacketsState send_state = this->SendPackets(true);
if (send_state != SPS_CLOSED) {
@ -2281,7 +2281,7 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci)
/* ci is nullptr when replaying, or for AIs. In neither case there is a client. */
ci->client_playas = c->index;
NetworkUpdateClientInfo(ci->client_id);
NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index, 0);
NetworkSendCommand(0, 0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name, c->index, 0);
}
/* Announce new company on network. */

@ -220,7 +220,7 @@ CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1,
/* We need to circumvent the "prevention" from this command being executed
* while the game is paused, so use the internal method. Nor do we want
* this command to get its cost estimated when shift is pressed. */
DoCommandPInternal(ob->tile, 0, user, CMD_CLEAR_ORDER_BACKUP, nullptr, nullptr, true, false, 0);
DoCommandPInternal(ob->tile, 0, user, 0, CMD_CLEAR_ORDER_BACKUP, nullptr, nullptr, true, false, 0);
} else {
/* The command came from the game logic, i.e. the clearing of a tile.
* In that case we have no need to actually sync this, just do it. */

@ -230,7 +230,7 @@ struct Plan : PlanPool::PoolItem<&_plan_pool> {
const TileIndex *buffer = this->temp_line->Export(&buffer_length);
if (buffer) {
_current_plan->SetVisibility(true, false);
ret = DoCommandP(0, _current_plan->index, (uint32) this->temp_line->tiles.size(), CMD_ADD_PLAN_LINE, nullptr, (const char *) buffer, true, buffer_length);
ret = DoCommandPEx(0, _current_plan->index, (uint32) this->temp_line->tiles.size(), 0, CMD_ADD_PLAN_LINE, nullptr, (const char *) buffer, buffer_length);
free(buffer);
}
_current_plan->temp_line->MarkDirty();

@ -53,7 +53,7 @@ CommandCost CmdAddPlan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2
* @param binary_length binary length of text
* @return the cost of this operation or an error
*/
CommandCost CmdAddPlanLine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length)
CommandCost CmdAddPlanLine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length)
{
Plan *p = Plan::GetIfValid(p1);
if (p == nullptr) return CMD_ERROR;

@ -403,7 +403,7 @@ void ShowPlansWindow()
* Only the creator of a plan executes this function.
* The other players should not be bothered with these changes.
*/
void CcAddPlan(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcAddPlan(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

@ -94,24 +94,22 @@ static bool IsStationAvailable(const StationSpec *statspec)
return Convert8bitBooleanCallback(statspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res);
}
void CcPlaySound_SPLAT_RAIL(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcPlaySound_SPLAT_RAIL(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
}
static CommandContainer GenericPlaceRailCmd(TileIndex tile, Track track)
{
CommandContainer ret = {
CommandContainer ret = NewCommandContainerBasic(
tile, // tile
_cur_railtype, // p1
track, // p2
(uint32) (_remove_button_clicked ?
CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)), // cmd
CcPlaySound_SPLAT_RAIL, // callback
0,
"" // text
};
CcPlaySound_SPLAT_RAIL // callback
);
return ret;
}
@ -145,7 +143,7 @@ static const DiagDirection _place_depot_extra_dir[12] = {
DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_NW, DIAGDIR_NE,
};
void CcRailDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcRailDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -186,7 +184,7 @@ static void PlaceRail_Waypoint(TileIndex tile)
}
}
void CcStation(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcStation(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -215,7 +213,7 @@ static void PlaceRail_Station(TileIndex tile)
int h = _settings_client.gui.station_platlength;
if (!_railstation.orientation) Swap(w, h);
CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, 0, "" };
CommandContainer cmdcont = NewCommandContainerBasic(tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation);
ShowSelectStationIfNeeded(cmdcont, TileArea(tile, w, h));
}
}
@ -306,7 +304,7 @@ static void PlaceRail_Bridge(TileIndex tile, Window *w)
}
/** Command callback for building a tunnel */
void CcBuildRailTunnel(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildRailTunnel(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
@ -387,17 +385,15 @@ static void BuildRailClick_Remove(Window *w)
static CommandContainer DoRailroadTrackCmd(TileIndex start_tile, TileIndex end_tile, Track track)
{
CommandContainer ret = {
CommandContainer ret = NewCommandContainerBasic(
start_tile, // tile
end_tile, // p1
(uint32) (_cur_railtype | (track << 6)), // p2
(uint32) (_remove_button_clicked ?
CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)), // cmd
CcPlaySound_SPLAT_RAIL, // callback
0,
"" // text
};
CcPlaySound_SPLAT_RAIL // callback
);
return ret;
}
@ -843,7 +839,7 @@ struct BuildRailToolbarWindow : Window {
uint32 p1 = _cur_railtype | (select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y) << 6 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24;
uint32 p2 = STAT_CLASS_WAYP | _cur_waypoint_type << 8 | INVALID_STATION << 16;
CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT), CcPlaySound_SPLAT_RAIL, 0, "" };
CommandContainer cmdcont = NewCommandContainerBasic(ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT), CcPlaySound_SPLAT_RAIL);
ShowSelectWaypointIfNeeded(cmdcont, ta);
}
}
@ -1008,7 +1004,7 @@ static void HandleStationPlacement(TileIndex start, TileIndex end)
uint32 p1 = _cur_railtype | _railstation.orientation << 6 | numtracks << 8 | platlength << 16 | _ctrl_pressed << 24;
uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16;
CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, 0, "" };
CommandContainer cmdcont = NewCommandContainerBasic(ta.tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation);
ShowSelectStationIfNeeded(cmdcont, ta);
}

@ -67,7 +67,7 @@ static RoadType _cur_roadtype;
static DiagDirection _road_depot_orientation;
static DiagDirection _road_station_picker_orientation;
void CcPlaySound_SPLAT_OTHER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcPlaySound_SPLAT_OTHER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
}
@ -97,7 +97,7 @@ static void PlaceRoad_Bridge(TileIndex tile, Window *w)
* @param p2 unused
* @param cmd unused
*/
void CcBuildRoadTunnel(const CommandCost &result, TileIndex start_tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildRoadTunnel(const CommandCost &result, TileIndex start_tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, start_tile);
@ -130,7 +130,7 @@ void ConnectRoadToStructure(TileIndex tile, DiagDirection direction)
}
}
void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -156,7 +156,7 @@ void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
* @param cmd Unused.
* @see CmdBuildRoadStop
*/
void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -193,7 +193,7 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, u
p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4.
TileArea ta(start_tile, end_tile);
CommandContainer cmdcont = { ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, CcRoadStop, 0, "" };
CommandContainer cmdcont = NewCommandContainerBasic(ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, CcRoadStop);
ShowSelectStationIfNeeded(cmdcont, ta);
}

@ -84,23 +84,25 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return GetStorage()->mode_instance;
}
/* static */ void ScriptObject::SetLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
/* static */ void ScriptObject::SetLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
ScriptStorage *s = GetStorage();
DEBUG(script, 6, "SetLastCommand company=%02d tile=%06x p1=%08x p2=%08x cmd=%d", s->root_company, tile, p1, p2, cmd);
DEBUG(script, 6, "SetLastCommand company=%02d tile=%06x p1=%08x p2=%08x p3=" OTTD_PRINTFHEX64PAD " cmd=%d", s->root_company, tile, p1, p2, p3, cmd);
s->last_tile = tile;
s->last_p1 = p1;
s->last_p2 = p2;
s->last_p3 = p3;
s->last_cmd = cmd & CMD_ID_MASK;
}
/* static */ bool ScriptObject::CheckLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
/* static */ bool ScriptObject::CheckLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
ScriptStorage *s = GetStorage();
DEBUG(script, 6, "CheckLastCommand company=%02d tile=%06x p1=%08x p2=%08x cmd=%d", s->root_company, tile, p1, p2, cmd);
DEBUG(script, 6, "CheckLastCommand company=%02d tile=%06x p1=%08x p2=%08x p3=" OTTD_PRINTFHEX64PAD " cmd=%d", s->root_company, tile, p1, p2, p3, cmd);
if (s->last_tile != tile) return false;
if (s->last_p1 != p1) return false;
if (s->last_p2 != p2) return false;
if (s->last_p3 != p3) return false;
if (s->last_cmd != (cmd & CMD_ID_MASK)) return false;
return true;
}
@ -300,7 +302,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return GetStorage()->callback_value[index];
}
/* static */ bool ScriptObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text, Script_SuspendCallbackProc *callback)
/* static */ bool ScriptObject::DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd, const char *text, uint32 binary_length, Script_SuspendCallbackProc *callback)
{
if (!ScriptObject::CanSuspend()) {
throw Script_FatalError("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator.");
@ -311,7 +313,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return false;
}
if (!StrEmpty(text) && (GetCommandFlags(cmd) & CMD_STR_CTRL) == 0) {
if (binary_length == 0 && !StrEmpty(text) && (GetCommandFlags(cmd) & CMD_STR_CTRL) == 0) {
/* The string must be valid, i.e. not contain special codes. Since some
* can be made with GSText, make sure the control codes are removed. */
::str_validate(const_cast<char *>(text), text + strlen(text), SVS_NONE);
@ -326,14 +328,14 @@ ScriptObject::ActiveInstance::~ActiveInstance()
/* Only set p2 when the command does not come from the network. */
if (GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = UINT32_MAX;
SCOPE_INFO_FMT([=], "ScriptObject::DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, company: %s, cmd: 0x%X (%s), estimate_only: %d",
tile, TileX(tile), TileY(tile), p1, p2, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), estimate_only);
SCOPE_INFO_FMT([=], "ScriptObject::DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, p3: 0x" OTTD_PRINTFHEX64 ", company: %s, cmd: 0x%X (%s), estimate_only: %d",
tile, TileX(tile), TileY(tile), p1, p2, p3, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), estimate_only);
/* Store the command for command callback validation. */
if (!estimate_only && _networking && !_generating_world) SetLastCommand(tile, p1, p2, cmd);
if (!estimate_only && _networking && !_generating_world) SetLastCommand(tile, p1, p2, p3, cmd);
/* Try to perform the command. */
CommandCost res = ::DoCommandPScript(tile, p1, p2, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, text, false, estimate_only, 0);
CommandCost res = ::DoCommandPScript(tile, p1, p2, p3, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, text, false, estimate_only, binary_length);
/* We failed; set the error and bail out */
if (res.Failed()) {

@ -69,17 +69,22 @@ protected:
/**
* Executes a raw DoCommand for the script.
*/
static bool DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text = nullptr, Script_SuspendCallbackProc *callback = nullptr);
static bool DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd, const char *text = nullptr, uint32 binary_length = 0, Script_SuspendCallbackProc *callback = nullptr);
static bool DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text = nullptr, Script_SuspendCallbackProc *callback = nullptr)
{
return ScriptObject::DoCommandEx(tile, p1, p2, 0, cmd, text, 0, callback);
}
/**
* Store the latest command executed by the script.
*/
static void SetLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd);
static void SetLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd);
/**
* Check if it's the latest command executed by the script.
*/
static bool CheckLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd);
static bool CheckLastCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd);
/**
* Sets the DoCommand costs counter to a value.

@ -720,11 +720,11 @@ void ScriptInstance::LimitOpsTillSuspend(SQInteger suspend)
}
}
bool ScriptInstance::DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
bool ScriptInstance::DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
ScriptObject::ActiveInstance active(this);
if (!ScriptObject::CheckLastCommand(tile, p1, p2, cmd)) {
if (!ScriptObject::CheckLastCommand(tile, p1, p2, p3, cmd)) {
DEBUG(script, 1, "DoCommandCallback terminating a script, last command does not match expected command");
return false;
}
@ -738,7 +738,7 @@ bool ScriptInstance::DoCommandCallback(const CommandCost &result, TileIndex tile
ScriptObject::SetLastCost(result.GetCost());
}
ScriptObject::SetLastCommand(INVALID_TILE, 0, 0, CMD_END);
ScriptObject::SetLastCommand(INVALID_TILE, 0, 0, 0, CMD_END);
return true;
}

@ -182,10 +182,11 @@ public:
* @param tile The tile on which the command was executed.
* @param p1 p1 as given to DoCommandPInternal.
* @param p2 p2 as given to DoCommandPInternal.
* @param p3 p3 as given to DoCommandPInternal.
* @param cmd cmd as given to DoCommandPInternal.
* @return true if we handled result.
*/
bool DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd);
bool DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd);
/**
* Insert an event for this script.

@ -47,6 +47,7 @@ private:
TileIndex last_tile; ///< The last tile passed to a command.
uint32 last_p1; ///< The last p1 passed to a command.
uint32 last_p2; ///< The last p2 passed to a command.
uint64 last_p3; ///< The last p3 passed to a command.
uint32 last_cmd; ///< The last cmd passed to a command.
VehicleID new_vehicle_id; ///< The ID of the new Vehicle.
@ -79,6 +80,7 @@ public:
last_tile (INVALID_TILE),
last_p1 (0),
last_p2 (0),
last_p3 (0),
last_cmd (CMD_END),
new_vehicle_id (0),
new_sign_id (0),

@ -2310,7 +2310,7 @@ void SyncCompanySettings()
const void *new_var = GetVariableAddress(&_settings_client.company, &sd->save);
uint32 old_value = (uint32)ReadValue(old_var, sd->save.conv);
uint32 new_value = (uint32)ReadValue(new_var, sd->save.conv);
if (old_value != new_value) NetworkSendCommand(0, i, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, nullptr, _local_company, 0);
if (old_value != new_value) NetworkSendCommand(0, i, new_value, 0, CMD_CHANGE_COMPANY_SETTING, nullptr, nullptr, _local_company, 0);
}
}

@ -116,7 +116,7 @@ CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
* @param p2 unused
* @param cmd unused
*/
void CcPlaceSign(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcPlaceSign(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

@ -602,7 +602,7 @@ void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *create_window_open
new TemplateCreateWindow(&_template_create_window_desc, to_edit, create_window_open);
}
void CcSetVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcSetVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -614,7 +614,7 @@ void CcSetVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uin
}
}
void CcVirtualTrainWagonsMoved(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcVirtualTrainWagonsMoved(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -625,7 +625,7 @@ void CcVirtualTrainWagonsMoved(const CommandCost &result, TileIndex tile, uint32
}
}
void CcDeleteVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcDeleteVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

@ -39,7 +39,7 @@
#include "safeguards.h"
void CcTerraform(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcTerraform(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);

@ -143,7 +143,7 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint32 val,
* @param text LE uint16 Order index to modify.
* @return the cost of this operation or an error
*/
CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length)
CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length)
{
VehicleID veh = GB(p1, 0, 20);
@ -313,7 +313,7 @@ CommandCost CmdBulkChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p
char text[2];
*reinterpret_cast<uint16 *>(&text) = TO_LE16(order_number);
DoCommand(tile, p1, p2, flags, CMD_CHANGE_TIMETABLE, text, 2);
DoCommandEx(tile, p1, p2, 0, flags, CMD_CHANGE_TIMETABLE, text, 2);
}
}

@ -716,7 +716,7 @@ struct TimetableWindow : Window {
} else {
char text[2];
*reinterpret_cast<uint16 *>(&text) = TO_LE16(order_number);
DoCommandP(0, p1, p2, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, text, true, 2);
DoCommandPEx(0, p1, p2, 0, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, text, 2);
}
}

@ -628,7 +628,7 @@ static CallBackFunction MenuClickCompany(int index)
if (_network_server) {
DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL);
} else {
NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, 0);
NetworkSendCommand(0, CCA_NEW, 0, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, 0);
}
return CBF_NONE;

@ -1027,7 +1027,7 @@ void ShowTownDirectory()
new TownDirectoryWindow(&_town_directory_desc);
}
void CcFoundTown(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcFoundTown(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -1035,7 +1035,7 @@ void CcFoundTown(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
}
void CcFoundRandomTown(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcFoundRandomTown(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) ScrollMainWindowToTile(Town::Get(_new_town_id)->xy);
}
@ -1986,15 +1986,13 @@ static void PlaceProc_House(TileIndex tile)
towns.resize(16);
}
CommandContainer cmd = {
CommandContainer cmd = NewCommandContainerBasic(
tile,
_cur_house, // p1 - house type and town index (town not yet set)
InteractiveRandom(), // p2 - random bits for the house
CMD_BUILD_HOUSE | CMD_MSG(STR_ERROR_CAN_T_BUILD_HOUSE_HERE),
CcPlaySound_SPLAT_RAIL,
0,
""
};
CcPlaySound_SPLAT_RAIL
);
if (!_ctrl_pressed) {
SB(cmd.p1, 16, 16, towns[0]); // set the town, it's alone on the list

@ -29,7 +29,7 @@ uint16 GetTrainVehicleMaxSpeed(const Train *u, const RailVehicleInfo *rvi_u, con
* @param p2 Additional data for the command (for the #CommandProc)
* @param cmd Unused.
*/
void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

@ -88,7 +88,7 @@ static CommandCost GetRefitCost(const Vehicle *v, EngineID engine_type, CargoID
* @param text unused
* @return the cost of this operation or an error
*/
CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length)
CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
/* Elementary check for valid location. */
if (!IsDepotTile(tile)) return CMD_ERROR;

@ -3085,7 +3085,7 @@ static const uint32 _vehicle_command_translation_table[][4] = {
* @param p1 vehicle ID
* @param p2 unused
*/
void CcStartStopVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcStartStopVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
@ -3738,7 +3738,7 @@ void StopGlobalFollowVehicle(const Vehicle *v)
* @param p2 unused
* @param cmd unused
*/
void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;

Loading…
Cancel
Save