Add third DoCommand parameter p3

This commit is contained in:
Jonathan G Rennison
2020-10-17 14:42:46 +01:00
parent 5c43de8ef8
commit bbbda0739b
39 changed files with 179 additions and 160 deletions

View File

@@ -98,7 +98,7 @@ ScriptInfo *AIInstance::FindLibrary(const char *library, int version)
* @param p2 p2 as given to DoCommandPInternal. * @param p2 p2 as given to DoCommandPInternal.
* @param cmd cmd 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. * 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); const Company *c = Company::GetIfValid(_current_company);
if (c == nullptr || c->ai_instance == nullptr) return; 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(); c->ai_instance->Continue();
} }
} }

View File

@@ -40,7 +40,7 @@ static void ShowBuildAirportPicker(Window *parent);
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout); 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; 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(); uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
p1 |= _selected_airport_layout << 8; 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)); ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE));
} }

View File

@@ -59,7 +59,7 @@ typedef GUIList<BuildBridgeData> GUIBridgeList; ///< List of bridges, used in #B
* - p2 = (bit 15-16) - transport type. * - p2 = (bit 15-16) - transport type.
* @param cmd unused * @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 (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, end_tile); if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, end_tile);

View File

@@ -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; 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; if (result.Failed()) return;

View File

@@ -88,7 +88,7 @@ CommandProc CmdPlantTree;
CommandProc CmdMoveRailVehicle; CommandProc CmdMoveRailVehicle;
CommandProcEx CmdBuildVehicle; CommandProc CmdBuildVehicle;
CommandProc CmdSellVehicle; CommandProc CmdSellVehicle;
CommandProc CmdRefitVehicle; CommandProc CmdRefitVehicle;
CommandProc CmdSendVehicleToDepot; CommandProc CmdSendVehicleToDepot;
@@ -524,6 +524,7 @@ struct CommandLogEntry {
uint32 p1; uint32 p1;
uint32 p2; uint32 p2;
uint32 cmd; uint32 cmd;
uint64 p3;
Date date; Date date;
DateFract date_fract; DateFract date_fract;
uint8 tick_skip_counter; uint8 tick_skip_counter;
@@ -533,8 +534,8 @@ struct CommandLogEntry {
CommandLogEntry() { } CommandLogEntry() { }
CommandLogEntry(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandLogEntryFlag log_flags) CommandLogEntry(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, 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), : 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) { } 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 | ", 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_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')); 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", buffer += seprintf(buffer, last, " %7d x %7d, p1: 0x%08X, p2: 0x%08X, ",
TileX(entry.tile), TileY(entry.tile), entry.p1, entry.p2, (uint) entry.current_company, (uint) entry.local_company, entry.cmd, GetCommandName(entry.cmd)); 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; 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 { struct cmd_text_info_dumper {
const char *CommandTextInfo(const char *text, uint32 binary_length) const char *CommandTextInfo(const char *text, uint32 binary_length)
{ {
@@ -715,10 +708,10 @@ private:
* @see CommandProc * @see CommandProc
* @return the cost * @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", 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, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), cmd_text_info_dumper().CommandTextInfo(text, binary_length)); 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; 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 || !(flags & DC_EXEC) ) {
if (_docommand_recursive == 1) _cleared_object_areas.clear(); if (_docommand_recursive == 1) _cleared_object_areas.clear();
SetTownRatingTestMode(true); 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); SetTownRatingTestMode(false);
if (res.Failed()) { if (res.Failed()) {
goto error; 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 /* Execute the command here. All cost-relevant functions set the expenses type
* themselves to the cost object at some point */ * themselves to the cost object at some point */
if (_docommand_recursive == 1) _cleared_object_areas.clear(); 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()) { if (res.Failed()) {
error: error:
_docommand_recursive--; _docommand_recursive--;
@@ -785,7 +778,7 @@ Money GetAvailableMoneyForCommand()
return Company::Get(company)->money; 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 (res.Failed()) log_flags |= CLEF_CMD_FAILED;
if (_generating_world) log_flags |= CLEF_GENERATING_WORLD; 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) { if (_networking && cmd_log.count > 0) {
CommandLogEntry &current = cmd_log.log[(cmd_log.next - 1) % cmd_log.log.size()]; 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 && 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.date_fract == _date_fract && current.tick_skip_counter == _tick_skip_counter &&
current.current_company == _current_company && current.local_company == _local_company) { current.current_company == _current_company && current.local_company == _local_company) {
current.log_flags |= log_flags | CLEF_TWICE; current.log_flags |= log_flags | CLEF_TWICE;
@@ -803,22 +796,11 @@ static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32
return; 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.next = (cmd_log.next + 1) % cmd_log.log.size();
cmd_log.count++; 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. * 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 * 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 tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc) * @param p1 Additional data for the command (see #CommandProc)
* @param p2 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 cmd The command to execute (a CMD_* value)
* @param callback A callback function to call after the command is finished * @param callback A callback function to call after the command is finished
* @param text The text to pass * @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 * @param binary_length The length of binary data in text
* @return \c true if the command succeeded, else \c false. * @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", 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, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), my_cmd, cmd_text_info_dumper().CommandTextInfo(text, binary_length)); 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 /* Cost estimation is generally only done when the
* local user presses shift while doing something. * 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. */ /* 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; 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; CommandLogEntryFlag log_flags;
log_flags = CLEF_NONE; 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 (only_sending) log_flags |= CLEF_ONLY_SENDING;
if (my_cmd) log_flags |= CLEF_MY_CMD; if (my_cmd) log_flags |= CLEF_MY_CMD;
if (binary_length > 0) log_flags |= CLEF_BINARY; 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()) { if (res.Failed()) {
/* Only show the error when it's for us. */ /* 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) { if (!estimate_only && !only_sending && callback != nullptr) {
callback(res, tile, p1, p2, cmd); callback(res, tile, p1, p2, p3, cmd);
} }
return res.Succeeded(); 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; CommandLogEntryFlag log_flags;
log_flags = CLEF_SCRIPT; 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 (_networking && !(cmd & CMD_NETWORK_COMMAND)) log_flags |= CLEF_ONLY_SENDING;
if (my_cmd) log_flags |= CLEF_MY_CMD; if (my_cmd) log_flags |= CLEF_MY_CMD;
if (binary_length > 0) log_flags |= CLEF_BINARY; 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; 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 tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc) * @param p1 Additional data for the command (see #CommandProc)
* @param p2 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 cmd The command to execute (a CMD_* value)
* @param callback A callback function to call after the command is finished * @param callback A callback function to call after the command is finished
* @param text The text to pass * @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 * @param estimate_only whether to give only the estimate or also execute the command
* @return the command cost of this function. * @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 */ /* Prevent recursion; it gives a mess over the network */
assert(_docommand_recursive == 0); assert(_docommand_recursive == 0);
@@ -987,13 +971,13 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
_cleared_object_areas.clear(); _cleared_object_areas.clear();
SetTownRatingTestMode(true); SetTownRatingTestMode(true);
BasePersistentStorageArray::SwitchMode(PSM_ENTER_TESTMODE); 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); BasePersistentStorageArray::SwitchMode(PSM_LEAVE_TESTMODE);
SetTownRatingTestMode(false); SetTownRatingTestMode(false);
if (!random_state.Check()) { 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)", 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, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd)); (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()); DEBUG(desync, 0, "msg: date{%08x; %02x; %02x}; %s", _date, _date_fract, _tick_skip_counter, msg.c_str());
LogDesyncMsg(std::move(msg)); 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) { if (!_networking || _generating_world || (cmd & CMD_NETWORK_COMMAND) != 0) {
/* Log the failed command as well. Just to be able to be find /* Log the failed command as well. Just to be able to be find
* causes of desyncs due to bad command test implementations. */ * 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)", 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, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd)); _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(); cur_company.Restore();
return_dcpi(res); 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 * send it to the command-queue and abort execution
*/ */
if (_networking && !_generating_world && !(cmd & CMD_NETWORK_COMMAND)) { 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(); cur_company.Restore();
/* Don't return anything special here; no error, no costs. /* 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. */ * reset the storages as we've not executed the command. */
return_dcpi(CommandCost()); 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)", 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, cmd & ~CMD_NETWORK_COMMAND, text, binary_length, GetCommandName(cmd)); _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 /* Actually try and execute the command. If no cost-type is given
* use the construction one */ * use the construction one */
_cleared_object_areas.clear(); _cleared_object_areas.clear();
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND); 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); BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND);
if (cmd_id == CMD_COMPANY_CTRL) { if (cmd_id == CMD_COMPANY_CTRL) {

View File

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

View File

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

View File

@@ -119,7 +119,7 @@ extern void DepotSortList(VehicleList *list);
* @param p2 unused * @param p2 unused
* @param cmd 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; if (result.Failed()) return;

View File

@@ -38,7 +38,7 @@ static void ShowBuildDocksDepotPicker(Window *parent);
static Axis _ship_depot_direction; 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; 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(); 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); 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 uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join
/* tile is always the land tile, so need to evaluate _thd.pos */ /* 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. */ /* Determine the watery part of the dock. */
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));

View File

@@ -85,11 +85,12 @@ void GameInstance::Died()
* @param tile The tile on which the command was executed. * @param tile The tile on which the command was executed.
* @param p1 p1 as given to DoCommandPInternal. * @param p1 p1 as given to DoCommandPInternal.
* @param p2 p2 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. * @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(); Game::GetGameInstance()->Continue();
} }
} }

View File

@@ -1212,7 +1212,7 @@ static inline VehicleGroupWindow *FindVehicleGroupWindow(VehicleType vt, Owner o
* @param cmd Unused. * @param cmd Unused.
* @see CmdCreateGroup * @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; if (result.Failed()) return;
assert(p1 <= VEH_AIRCRAFT); 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 p2 Bit 0-19: Vehicle ID.
* @param cmd Unused. * @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; if (result.Failed()) return;
assert(Vehicle::IsValidID(GB(p2, 0, 20))); 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);
} }
/** /**

View File

@@ -222,7 +222,7 @@ void SortIndustryTypes()
* @param p2 Additional data of the #CMD_BUILD_INDUSTRY command. * @param p2 Additional data of the #CMD_BUILD_INDUSTRY command.
* @param cmd Unused. * @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; if (result.Succeeded()) return;

View File

@@ -48,7 +48,7 @@
#include "safeguards.h" #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; 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); if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_12_EXPLOSION, tile);
} }

View File

@@ -901,8 +901,8 @@ void NetworkGameLoop()
while (f != nullptr && !feof(f)) { while (f != nullptr && !feof(f)) {
if (_date == next_date && _date_fract == next_date_fract) { if (_date == next_date && _date_fract == next_date_fract) {
if (cp != nullptr) { 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); 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; %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)); 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(); cp.reset();
} }
if (check_sync_state) { if (check_sync_state) {
@@ -941,11 +941,12 @@ void NetworkGameLoop()
int company; int company;
cp->text.resize(MAX_CMD_TEXT_LENGTH); cp->text.resize(MAX_CMD_TEXT_LENGTH);
assert_compile(MAX_CMD_TEXT_LENGTH > 8192); 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())); 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[^\"]\"",
/* There are 9 pieces of data to read, however the last is a &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 that might or might not exist. Ignore it if that
* string misses because in 99% of the time it's not used. */ * 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->company = (CompanyID)company;
cp->binary_length = 0; cp->binary_length = 0;
} else if (strncmp(p, "join: ", 6) == 0) { } else if (strncmp(p, "join: ", 6) == 0) {
@@ -959,6 +960,7 @@ void NetworkGameLoop()
cp->cmd = CMD_PAUSE; cp->cmd = CMD_PAUSE;
cp->p1 = PM_PAUSED_NORMAL; cp->p1 = PM_PAUSED_NORMAL;
cp->p2 = 1; cp->p2 = 1;
cp->p3 = 0;
cp->callback = nullptr; cp->callback = nullptr;
cp->binary_length = 0; cp->binary_length = 0;
_ddc_fastforward = false; _ddc_fastforward = false;

View File

@@ -993,7 +993,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
* the server will give us a client-id and let us in */ * the server will give us a client-id and let us in */
_network_join_status = NETWORK_JOIN_STATUS_REGISTERING; _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
ShowJoinStatusWindow(); 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 { } else {
/* take control over an existing company */ /* take control over an existing company */

View File

@@ -137,13 +137,14 @@ static CommandQueue _local_execution_queue;
* @param tile The tile to perform a command on (see #CommandProc) * @param tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc) * @param p1 Additional data for the command (see #CommandProc)
* @param p2 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 cmd The command to execute (a CMD_* value)
* @param callback A callback function to call after the command is finished * @param callback A callback function to call after the command is finished
* @param text The text to pass * @param text The text to pass
* @param company The company that wants to send the command * @param company The company that wants to send the command
* @param binary_length The quantity of binary data in text * @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); 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.tile = tile;
c.p1 = p1; c.p1 = p1;
c.p2 = p2; c.p2 = p2;
c.p3 = p3;
c.cmd = cmd; c.cmd = cmd;
c.callback = callback; c.callback = callback;
@@ -320,6 +322,7 @@ const char *NetworkGameSocketHandler::ReceiveCommand(Packet *p, CommandPacket *c
cp->p1 = p->Recv_uint32(); cp->p1 = p->Recv_uint32();
cp->p2 = p->Recv_uint32(); cp->p2 = p->Recv_uint32();
cp->p3 = p->Recv_uint64();
cp->tile = p->Recv_uint32(); cp->tile = p->Recv_uint32();
cp->binary_length = p->Recv_uint32(); cp->binary_length = p->Recv_uint32();
if (cp->binary_length == 0) { 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->cmd);
p->Send_uint32(cp->p1); p->Send_uint32(cp->p1);
p->Send_uint32(cp->p2); p->Send_uint32(cp->p2);
p->Send_uint64(cp->p3);
p->Send_uint32(cp->tile); p->Send_uint32(cp->tile);
p->Send_uint32(cp->binary_length); p->Send_uint32(cp->binary_length);
if (cp->binary_length == 0) { if (cp->binary_length == 0) {

View File

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

View File

@@ -220,7 +220,7 @@ CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1,
/* We need to circumvent the "prevention" from this command being executed /* 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 * 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. */ * 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 { } else {
/* The command came from the game logic, i.e. the clearing of a tile. /* 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. */ * In that case we have no need to actually sync this, just do it. */

View File

@@ -230,7 +230,7 @@ struct Plan : PlanPool::PoolItem<&_plan_pool> {
const TileIndex *buffer = this->temp_line->Export(&buffer_length); const TileIndex *buffer = this->temp_line->Export(&buffer_length);
if (buffer) { if (buffer) {
_current_plan->SetVisibility(true, false); _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); free(buffer);
} }
_current_plan->temp_line->MarkDirty(); _current_plan->temp_line->MarkDirty();

View File

@@ -53,7 +53,7 @@ CommandCost CmdAddPlan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2
* @param binary_length binary length of text * @param binary_length binary length of text
* @return the cost of this operation or an error * @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); Plan *p = Plan::GetIfValid(p1);
if (p == nullptr) return CMD_ERROR; if (p == nullptr) return CMD_ERROR;

View File

@@ -403,7 +403,7 @@ void ShowPlansWindow()
* Only the creator of a plan executes this function. * Only the creator of a plan executes this function.
* The other players should not be bothered with these changes. * 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; if (result.Failed()) return;

View File

@@ -94,24 +94,22 @@ static bool IsStationAvailable(const StationSpec *statspec)
return Convert8bitBooleanCallback(statspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res); 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); if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
} }
static CommandContainer GenericPlaceRailCmd(TileIndex tile, Track track) static CommandContainer GenericPlaceRailCmd(TileIndex tile, Track track)
{ {
CommandContainer ret = { CommandContainer ret = NewCommandContainerBasic(
tile, // tile tile, // tile
_cur_railtype, // p1 _cur_railtype, // p1
track, // p2 track, // p2
(uint32) (_remove_button_clicked ? (uint32) (_remove_button_clicked ?
CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) : 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 CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)), // cmd
CcPlaySound_SPLAT_RAIL, // callback CcPlaySound_SPLAT_RAIL // callback
0, );
"" // text
};
return ret; return ret;
} }
@@ -145,7 +143,7 @@ static const DiagDirection _place_depot_extra_dir[12] = {
DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_NW, DIAGDIR_NE, 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; 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; if (result.Failed()) return;
@@ -215,7 +213,7 @@ static void PlaceRail_Station(TileIndex tile)
int h = _settings_client.gui.station_platlength; int h = _settings_client.gui.station_platlength;
if (!_railstation.orientation) Swap(w, h); 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)); ShowSelectStationIfNeeded(cmdcont, TileArea(tile, w, h));
} }
} }
@@ -306,7 +304,7 @@ static void PlaceRail_Bridge(TileIndex tile, Window *w)
} }
/** Command callback for building a tunnel */ /** 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 (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile); 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) static CommandContainer DoRailroadTrackCmd(TileIndex start_tile, TileIndex end_tile, Track track)
{ {
CommandContainer ret = { CommandContainer ret = NewCommandContainerBasic(
start_tile, // tile start_tile, // tile
end_tile, // p1 end_tile, // p1
(uint32) (_cur_railtype | (track << 6)), // p2 (uint32) (_cur_railtype | (track << 6)), // p2
(uint32) (_remove_button_clicked ? (uint32) (_remove_button_clicked ?
CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) : 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 CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)), // cmd
CcPlaySound_SPLAT_RAIL, // callback CcPlaySound_SPLAT_RAIL // callback
0, );
"" // text
};
return ret; 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 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; 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); 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 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; 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); ShowSelectStationIfNeeded(cmdcont, ta);
} }

View File

@@ -67,7 +67,7 @@ static RoadType _cur_roadtype;
static DiagDirection _road_depot_orientation; static DiagDirection _road_depot_orientation;
static DiagDirection _road_station_picker_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); 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 p2 unused
* @param cmd 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 (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, start_tile); 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; if (result.Failed()) return;
@@ -156,7 +156,7 @@ void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
* @param cmd Unused. * @param cmd Unused.
* @see CmdBuildRoadStop * @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; 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. p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4.
TileArea ta(start_tile, end_tile); 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); ShowSelectStationIfNeeded(cmdcont, ta);
} }

View File

@@ -84,23 +84,25 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return GetStorage()->mode_instance; 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(); 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_tile = tile;
s->last_p1 = p1; s->last_p1 = p1;
s->last_p2 = p2; s->last_p2 = p2;
s->last_p3 = p3;
s->last_cmd = cmd & CMD_ID_MASK; 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(); 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_tile != tile) return false;
if (s->last_p1 != p1) return false; if (s->last_p1 != p1) return false;
if (s->last_p2 != p2) 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; if (s->last_cmd != (cmd & CMD_ID_MASK)) return false;
return true; return true;
} }
@@ -300,7 +302,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return GetStorage()->callback_value[index]; 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()) { if (!ScriptObject::CanSuspend()) {
throw Script_FatalError("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator."); 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; 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 /* 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. */ * can be made with GSText, make sure the control codes are removed. */
::str_validate(const_cast<char *>(text), text + strlen(text), SVS_NONE); ::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. */ /* Only set p2 when the command does not come from the network. */
if (GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = UINT32_MAX; 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", 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, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), estimate_only); 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. */ /* 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. */ /* 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 */ /* We failed; set the error and bail out */
if (res.Failed()) { if (res.Failed()) {

View File

@@ -69,17 +69,22 @@ protected:
/** /**
* Executes a raw DoCommand for the script. * 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. * 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. * 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. * Sets the DoCommand costs counter to a value.

View File

@@ -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); 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"); DEBUG(script, 1, "DoCommandCallback terminating a script, last command does not match expected command");
return false; return false;
} }
@@ -738,7 +738,7 @@ bool ScriptInstance::DoCommandCallback(const CommandCost &result, TileIndex tile
ScriptObject::SetLastCost(result.GetCost()); ScriptObject::SetLastCost(result.GetCost());
} }
ScriptObject::SetLastCommand(INVALID_TILE, 0, 0, CMD_END); ScriptObject::SetLastCommand(INVALID_TILE, 0, 0, 0, CMD_END);
return true; return true;
} }

View File

@@ -182,10 +182,11 @@ public:
* @param tile The tile on which the command was executed. * @param tile The tile on which the command was executed.
* @param p1 p1 as given to DoCommandPInternal. * @param p1 p1 as given to DoCommandPInternal.
* @param p2 p2 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. * @param cmd cmd as given to DoCommandPInternal.
* @return true if we handled result. * @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. * Insert an event for this script.

View File

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

View File

@@ -2310,7 +2310,7 @@ void SyncCompanySettings()
const void *new_var = GetVariableAddress(&_settings_client.company, &sd->save); const void *new_var = GetVariableAddress(&_settings_client.company, &sd->save);
uint32 old_value = (uint32)ReadValue(old_var, sd->save.conv); uint32 old_value = (uint32)ReadValue(old_var, sd->save.conv);
uint32 new_value = (uint32)ReadValue(new_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);
} }
} }

View File

@@ -116,7 +116,7 @@ CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
* @param p2 unused * @param p2 unused
* @param cmd 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; if (result.Failed()) return;

View File

@@ -602,7 +602,7 @@ void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *create_window_open
new TemplateCreateWindow(&_template_create_window_desc, to_edit, 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; 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; 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; if (result.Failed()) return;

View File

@@ -39,7 +39,7 @@
#include "safeguards.h" #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 (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile); if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);

View File

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

View File

@@ -716,7 +716,7 @@ struct TimetableWindow : Window {
} else { } else {
char text[2]; char text[2];
*reinterpret_cast<uint16 *>(&text) = TO_LE16(order_number); *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);
} }
} }

View File

@@ -628,7 +628,7 @@ static CallBackFunction MenuClickCompany(int index)
if (_network_server) { if (_network_server) {
DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL); DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL);
} else { } 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; return CBF_NONE;

View File

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

View File

@@ -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 p2 Additional data for the command (for the #CommandProc)
* @param cmd Unused. * @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; if (result.Failed()) return;

View File

@@ -88,7 +88,7 @@ static CommandCost GetRefitCost(const Vehicle *v, EngineID engine_type, CargoID
* @param text unused * @param text unused
* @return the cost of this operation or an error * @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. */ /* Elementary check for valid location. */
if (!IsDepotTile(tile)) return CMD_ERROR; if (!IsDepotTile(tile)) return CMD_ERROR;

View File

@@ -3085,7 +3085,7 @@ static const uint32 _vehicle_command_translation_table[][4] = {
* @param p1 vehicle ID * @param p1 vehicle ID
* @param p2 unused * @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; if (result.Failed()) return;
@@ -3738,7 +3738,7 @@ void StopGlobalFollowVehicle(const Vehicle *v)
* @param p2 unused * @param p2 unused
* @param cmd 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; if (result.Failed()) return;