diff --git a/src/command.cpp b/src/command.cpp index 96f67ca44d..c9e744af3b 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -12,6 +12,7 @@ #include "error.h" #include "gui.h" #include "command_func.h" +#include "command_aux.h" #include "network/network_type.h" #include "network/network.h" #include "genworld.h" @@ -565,7 +566,7 @@ enum CommandLogEntryFlag : uint16 { CLEF_ESTIMATE_ONLY = 0x08, ///< estimate only CLEF_ONLY_SENDING = 0x10, ///< only sending CLEF_MY_CMD = 0x20, ///< locally generated command - CLEF_BINARY = 0x40, ///< binary_length is > 0 + CLEF_AUX_DATA = 0x40, ///< have auxiliary data CLEF_SCRIPT = 0x80, ///< command run by AI/game script CLEF_TWICE = 0x100, ///< command logged twice (only sending and execution) CLEF_RANDOM = 0x200, ///< command changed random seed @@ -648,7 +649,7 @@ static void DumpSubCommandLog(char *&buffer, const char *last, const CommandLog } buffer += seprintf(buffer, last, " | %c%c%c%c%c%c%c%c%c%c%c | ", fc(CLEF_ORDER_BACKUP, 'o'), fc(CLEF_RANDOM, 'r'), fc(CLEF_TWICE, '2'), - fc(CLEF_SCRIPT, 'a'), fc(CLEF_BINARY, 'b'), fc(CLEF_MY_CMD, 'm'), fc(CLEF_ONLY_SENDING, 's'), + fc(CLEF_SCRIPT, 'a'), fc(CLEF_AUX_DATA, '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, ", TileX(entry.tile), TileY(entry.tile), entry.p1, entry.p2); @@ -756,17 +757,15 @@ bool IsCommandAllowedWhilePaused(uint32 cmd) static int _docommand_recursive = 0; struct cmd_text_info_dumper { - const char *CommandTextInfo(const char *text, uint32 binary_length) + const char *CommandTextInfo(const char *text, const CommandAuxiliaryBase *aux_data) { char *b = this->buffer; const char *last = lastof(this->buffer); if (text) { - b += seprintf(b, last, ", text"); + b += seprintf(b, last, ", text: length: %u", (uint) strlen(text)); } - if (binary_length) { - b += seprintf(b, last, ", bin length: %u", binary_length); - } else if (text) { - b += seprintf(b, last, ", str length: %u", (uint) strlen(text)); + if (aux_data) { + b += seprintf(b, last, ", aux data"); } return this->buffer; } @@ -789,10 +788,10 @@ private: * @see CommandProc * @return the cost */ -CommandCost DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, 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, const CommandAuxiliaryBase *aux_data) { 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)); + tile, TileX(tile), TileY(tile), p1, p2, p3, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), cmd_text_info_dumper().CommandTextInfo(text, aux_data)); CommandCost res; @@ -808,7 +807,7 @@ CommandCost DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, DoComma 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, p3, text, binary_length); + res = command.Execute(tile, flags & ~DC_EXEC, p1, p2, p3, text, aux_data); SetTownRatingTestMode(false); if (res.Failed()) { goto error; @@ -830,7 +829,7 @@ CommandCost DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, DoComma /* 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, p3, text, binary_length); + res = command.Execute(tile, flags, p1, p2, p3, text, aux_data); if (res.Failed()) { error: _docommand_recursive--; @@ -909,10 +908,10 @@ static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32 * @param binary_length The length of binary data in text * @return \c true if the command succeeded, else \c false. */ -bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, uint32 binary_length, bool my_cmd) +bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, const CommandAuxiliaryBase *aux_data, bool my_cmd) { 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)); + tile, TileX(tile), TileY(tile), p1, p2, p3, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd), my_cmd, cmd_text_info_dumper().CommandTextInfo(text, aux_data)); /* Cost estimation is generally only done when the * local user presses shift while doing something. @@ -945,15 +944,15 @@ bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, C GameRandomSeedChecker random_state; uint order_backup_update_counter = OrderBackup::GetUpdateCounter(); - CommandCost res = DoCommandPInternal(tile, p1, p2, p3, cmd, callback, text, my_cmd, estimate_only, binary_length); + CommandCost res = DoCommandPInternal(tile, p1, p2, p3, cmd, callback, text, my_cmd, estimate_only, aux_data); CommandLogEntryFlag log_flags; log_flags = CLEF_NONE; - if (binary_length == 0 && !StrEmpty(text)) log_flags |= CLEF_TEXT; + if (!StrEmpty(text)) log_flags |= CLEF_TEXT; if (estimate_only) log_flags |= CLEF_ESTIMATE_ONLY; if (only_sending) log_flags |= CLEF_ONLY_SENDING; if (my_cmd) log_flags |= CLEF_MY_CMD; - if (binary_length > 0) log_flags |= CLEF_BINARY; + if (aux_data != nullptr) log_flags |= CLEF_AUX_DATA; if (!random_state.Check()) log_flags |= CLEF_RANDOM; if (order_backup_update_counter != OrderBackup::GetUpdateCounter()) log_flags |= CLEF_ORDER_BACKUP; AppendCommandLogEntry(res, tile, p1, p2, p3, cmd, log_flags, text); @@ -988,20 +987,20 @@ bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, C return res.Succeeded(); } -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 DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, const CommandAuxiliaryBase *aux_data) { GameRandomSeedChecker random_state; uint order_backup_update_counter = OrderBackup::GetUpdateCounter(); - CommandCost res = DoCommandPInternal(tile, p1, p2, p3, cmd, callback, text, my_cmd, estimate_only, binary_length); + CommandCost res = DoCommandPInternal(tile, p1, p2, p3, cmd, callback, text, my_cmd, estimate_only, aux_data); CommandLogEntryFlag log_flags; log_flags = CLEF_SCRIPT; - if (binary_length == 0 && !StrEmpty(text)) log_flags |= CLEF_TEXT; + if (!StrEmpty(text)) log_flags |= CLEF_TEXT; if (estimate_only) log_flags |= CLEF_ESTIMATE_ONLY; 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; + if (aux_data != nullptr) log_flags |= CLEF_AUX_DATA; if (!random_state.Check()) log_flags |= CLEF_RANDOM; if (order_backup_update_counter != OrderBackup::GetUpdateCounter()) log_flags |= CLEF_ORDER_BACKUP; AppendCommandLogEntry(res, tile, p1, p2, p3, cmd, log_flags, text); @@ -1063,7 +1062,7 @@ void EnqueueDoCommandP(CommandContainer cmd) * @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, 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, const CommandAuxiliaryBase *aux_data) { /* Prevent recursion; it gives a mess over the network */ assert(_docommand_recursive == 0); @@ -1113,13 +1112,13 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, _cleared_object_areas.clear(); SetTownRatingTestMode(true); BasePersistentStorageArray::SwitchMode(PSM_ENTER_TESTMODE); - CommandCost res = command.Execute(tile, flags, p1, p2, p3, text, binary_length); + CommandCost res = command.Execute(tile, flags, p1, p2, p3, text, aux_data); 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; 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)); + 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\"%s (%s)", + (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); DEBUG(desync, 0, "msg: date{%08x; %02x; %02x}; %s", _date, _date_fract, _tick_skip_counter, msg.c_str()); LogDesyncMsg(std::move(msg)); } @@ -1137,8 +1136,8 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, 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; 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)); + 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\"%s (%s)", + _date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); } cur_company.Restore(); return_dcpi(res); @@ -1149,7 +1148,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, * send it to the command-queue and abort execution */ if (_networking && !_generating_world && !(cmd & CMD_NETWORK_COMMAND)) { - NetworkSendCommand(tile, p1, p2, p3, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company, binary_length); + NetworkSendCommand(tile, p1, p2, p3, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company, aux_data); cur_company.Restore(); /* Don't return anything special here; no error, no costs. @@ -1158,14 +1157,14 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, * 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; 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)); + 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\"%s(%s)", + _date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", 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, p3, text, binary_length); + CommandCost res2 = command.Execute(tile, flags | DC_EXEC, p1, p2, p3, text, aux_data); BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND); if (cmd_id == CMD_COMPANY_CTRL) { diff --git a/src/command_func.h b/src/command_func.h index fd0446df00..e1d3b400dc 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -32,7 +32,7 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID); */ #define return_cmd_error(errcode) return CommandCost(errcode); -CommandCost DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, 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, const CommandAuxiliaryBase *aux_data = nullptr); inline CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = nullptr) { @@ -40,10 +40,10 @@ inline CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag } 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); + return DoCommandEx(container->tile, container->p1, container->p2, container->p3, flags, container->cmd & CMD_ID_MASK, container->text.c_str(), container->aux_data.get()); } -bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, uint32 binary_length, bool my_cmd = true); +bool DoCommandPEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, const CommandAuxiliaryBase *aux_data, 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) { @@ -52,13 +52,13 @@ inline bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Command 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); + return DoCommandPEx(container->tile, container->p1, container->p2, container->p3, container->cmd, container->callback, container->text.c_str(), container->aux_data.get(), 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); +CommandCost DoCommandPScript(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, const CommandAuxiliaryBase *aux_data); +CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only, const CommandAuxiliaryBase *aux_data); -void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, 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, const CommandAuxiliaryBase *aux_data); extern Money _additional_cash_required; diff --git a/src/command_type.h b/src/command_type.h index 0247b23b33..a37af9ec72 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -621,6 +621,8 @@ enum CommandPauseLevel { CMDPL_ALL_ACTIONS, ///< All actions may be executed. }; +struct CommandAuxiliaryBase; + /** * Defines the callback type for all command handler functions. * @@ -640,7 +642,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, uint64 p3, const char *text, uint32 binary_length); +typedef CommandCost CommandProcEx(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data); /** * Define a command with the flags which belongs to it. @@ -662,9 +664,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, uint64 p3, const char *text, uint32 binary_length) const { + inline CommandCost Execute(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) const { if (this->flags & CMD_PROCEX) { - return this->procex(tile, flags, p1, p2, p3, text, binary_length); + return this->procex(tile, flags, p1, p2, p3, text, aux_data); } else { return this->proc(tile, flags, p1, p2, text); } @@ -733,13 +735,13 @@ struct CommandContainer { 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. + CommandAuxiliaryPtr aux_data; ///< Auxiliary command data }; inline CommandContainer NewCommandContainerBasic(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = nullptr) { - return { tile, p1, p2, cmd, 0, callback, 0, {} }; + return { tile, p1, p2, cmd, 0, callback, {}, nullptr }; } #endif /* COMMAND_TYPE_H */ diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index ff4c26ce37..68388aec62 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -922,7 +922,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 /* In network games, we need to try setting the company manager face here to sync it to all clients. * If a favorite company manager face is selected, choose it. Otherwise, use a random face. */ - if (_company_manager_face != 0) NetworkSendCommand(0, 0, _company_manager_face, 0, CMD_SET_COMPANY_MANAGER_FACE, nullptr, nullptr, _local_company, 0); + if (_company_manager_face != 0) NetworkSendCommand(0, 0, _company_manager_face, 0, CMD_SET_COMPANY_MANAGER_FACE, nullptr, nullptr, _local_company, nullptr); /* Now that we have a new company, broadcast our company settings to * all clients so everything is in sync */ diff --git a/src/league_cmd.cpp b/src/league_cmd.cpp index b201025e8e..e74a1ac8de 100644 --- a/src/league_cmd.cpp +++ b/src/league_cmd.cpp @@ -190,7 +190,7 @@ CommandCost CmdCreateLeagueTable(TileIndex tile, DoCommandFlag flags, uint32 p1, return res; } -CommandCost CmdCreateLeagueTableElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdCreateLeagueTableElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { std::string text_str, score; text = StrConsumeToSeparator(text_str, text); @@ -227,7 +227,7 @@ CommandCost CmdUpdateLeagueTableElementData(TileIndex tile, DoCommandFlag flags, return CmdUpdateLeagueTableElementData(flags, element, company, text, link_type, link_target); } -CommandCost CmdUpdateLeagueTableElementScore(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdUpdateLeagueTableElementScore(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { return CmdUpdateLeagueTableElementScore(flags, p1, p3, text); } diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index fd252ab2d5..01803948b0 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -85,6 +85,13 @@ bool Packet::CanWriteToPacket(size_t bytes_to_write) return this->Size() + bytes_to_write <= this->limit; } +void Packet::WriteAtOffset_uint16(size_t offset, uint16 data) +{ + assert(offset + 1 < this->buffer.size()); + this->buffer[offset] = GB(data, 0, 8); + this->buffer[offset + 1] = GB(data, 8, 8); +} + /* diff --git a/src/network/core/packet.h b/src/network/core/packet.h index 8f1bbc2cb1..5b8cca594c 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -72,7 +72,9 @@ public: PacketSize &GetDeserialisationPosition() { return this->pos; } bool CanDeserialiseBytes(size_t bytes_to_read, bool raise_error) { return this->CanReadFromPacket(bytes_to_read, raise_error); } - bool CanWriteToPacket(size_t bytes_to_write); + bool CanWriteToPacket(size_t bytes_to_write); + + void WriteAtOffset_uint16(size_t offset, uint16); /* Reading/receiving of packets */ size_t ReadRawPacketSize() const; diff --git a/src/network/network.cpp b/src/network/network.cpp index 12acbb375d..33a2ac962e 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1120,7 +1120,7 @@ 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->p3, 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->aux_data); 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(); } @@ -1167,7 +1167,7 @@ void NetworkGameLoop() * string misses because in 99% of the time it's not used. */ assert(ret == 10 || ret == 9); cp->company = (CompanyID)company; - cp->binary_length = 0; + cp->aux_data = nullptr; } else if (strncmp(p, "join: ", 6) == 0) { /* Manually insert a pause when joining; this way the client can join at the exact right time. */ int ret = sscanf(p + 6, "date{%x; %x; %x}", &next_date, &next_date_fract, &next_tick_skip_counter); @@ -1181,7 +1181,7 @@ void NetworkGameLoop() cp->p2 = 1; cp->p3 = 0; cp->callback = nullptr; - cp->binary_length = 0; + cp->aux_data = nullptr; _ddc_fastforward = false; } else if (strncmp(p, "sync: ", 6) == 0) { int ret = sscanf(p + 6, "date{%x; %x; %x}; %x; %x", &next_date, &next_date_fract, &next_tick_skip_counter, &sync_state[0], &sync_state[1]); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index e5439b7c46..b58c461813 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1002,7 +1002,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, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, 0); + NetworkSendCommand(0, CCA_NEW, 0, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, nullptr); } } else { /* take control over an existing company */ diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index 51fc9619fc..fa47cc4b0f 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -12,6 +12,7 @@ #include "network_client.h" #include "network_server.h" #include "../command_func.h" +#include "../command_aux.h" #include "../company_func.h" #include "../settings_type.h" @@ -143,9 +144,9 @@ static CommandQueue _local_execution_queue; * @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 + * @param aux_data Auxiliary command data */ -void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, 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, const CommandAuxiliaryBase *aux_data) { assert((cmd & CMD_FLAGS_MASK) == 0); @@ -157,16 +158,12 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 c.p3 = p3; c.cmd = cmd; c.callback = callback; + if (aux_data != nullptr) c.aux_data.reset(aux_data->Clone()); - c.binary_length = binary_length; - if (binary_length == 0) { - if (text != nullptr) { - c.text.assign(text); - } else { - c.text.clear(); - } + if (text != nullptr) { + c.text.assign(text); } else { - c.text.assign(text, binary_length); + c.text.clear(); } if (_network_server) { @@ -328,21 +325,24 @@ const char *NetworkGameSocketHandler::ReceiveCommand(Packet *p, CommandPacket *c 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) { - StringValidationSettings settings = (!_network_server && GetCommandFlags(cp->cmd) & CMD_STR_CTRL) != 0 ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK; - if (GetCommandFlags(cp->cmd) & CMD_STR_SEP) settings |= SVS_ALLOW_SEPARATOR_CODE; - p->Recv_string(cp->text, settings); - } else { - if (!p->CanReadFromPacket(cp->binary_length + /* callback index */ 1)) return "invalid binary data length"; - if (cp->binary_length > MAX_CMD_TEXT_LENGTH) return "over-size binary data length"; - p->Recv_binary(cp->text, cp->binary_length); - } + + StringValidationSettings settings = (!_network_server && GetCommandFlags(cp->cmd) & CMD_STR_CTRL) != 0 ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK; + if (GetCommandFlags(cp->cmd) & CMD_STR_SEP) settings |= SVS_ALLOW_SEPARATOR_CODE; + p->Recv_string(cp->text, settings); byte callback = p->Recv_uint8(); if (callback >= lengthof(_callback_table)) return "invalid callback"; cp->callback = _callback_table[callback]; + + uint16 aux_data_size = p->Recv_uint16(); + if (aux_data_size > 0 && p->CanReadFromPacket(aux_data_size, true)) { + CommandAuxiliarySerialised *aux_data = new CommandAuxiliarySerialised(); + cp->aux_data.reset(aux_data); + aux_data->serialised_data.resize(aux_data_size); + p->Recv_binary((char *)(aux_data->serialised_data.data()), aux_data_size); + } + return nullptr; } @@ -359,13 +359,7 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp) 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) { - p->Send_string(cp->text.c_str()); - } else { - assert(cp->text.size() >= cp->binary_length); - p->Send_binary(cp->text.c_str(), cp->binary_length); - } + p->Send_string(cp->text.c_str()); byte callback = 0; while (callback < lengthof(_callback_table) && _callback_table[callback] != cp->callback) { @@ -377,4 +371,12 @@ void NetworkGameSocketHandler::SendCommand(Packet *p, const CommandPacket *cp) callback = 0; // _callback_table[0] == nullptr } p->Send_uint8 (callback); + + size_t aux_data_size_pos = p->Size(); + p->Send_uint16(0); + if (cp->aux_data != nullptr) { + CommandSerialisationBuffer serialiser(p->GetSerialisationBuffer(), p->GetSerialisationLimit()); + cp->aux_data->Serialise(serialiser); + p->WriteAtOffset_uint16(aux_data_size_pos, (uint16)(p->Size() - aux_data_size_pos - 2)); + } } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 0ca11bd4d6..905573ee83 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1563,7 +1563,7 @@ private: if (_network_server) { DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL); } else { - NetworkSendCommand(0, CCA_NEW, 0, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, 0); + NetworkSendCommand(0, CCA_NEW, 0, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company, nullptr); } } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 87d12a8143..207c52bec9 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1211,7 +1211,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p _settings_client.network.sync_freq = std::min(_settings_client.network.sync_freq, 16); // have the server and all clients run some sanity checks - NetworkSendCommand(0, 0, 0, 0, CMD_DESYNC_CHECK, nullptr, nullptr, _local_company, 0); + NetworkSendCommand(0, 0, 0, 0, CMD_DESYNC_CHECK, nullptr, nullptr, _local_company, nullptr); SendPacketsState send_state = this->SendPackets(true); if (send_state != SPS_CLOSED) { @@ -2301,7 +2301,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, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name.c_str(), c->index, 0); + NetworkSendCommand(0, 0, 0, 0, CMD_RENAME_PRESIDENT, nullptr, ci->client_name.c_str(), c->index, nullptr); } /* Announce new company on network. */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index cefb7411a7..5cffd99a6c 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -966,7 +966,7 @@ uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { VehicleID veh = GB(p1, 0, 20); VehicleOrderID sel_ord = GB(p2, 0, 16); @@ -1758,7 +1758,7 @@ CommandCost CmdReverseOrderList(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { VehicleOrderID sel_ord = GB(p3, 0, 16); VehicleID veh = GB(p1, 0, 20); diff --git a/src/plans.cpp b/src/plans.cpp index 1477825e24..9f75fce3df 100644 --- a/src/plans.cpp +++ b/src/plans.cpp @@ -47,3 +47,19 @@ void PlanLine::UpdateVisualExtents() this->viewport_extents = { (int)(min_x * TILE_SIZE * 2 * ZOOM_LVL_BASE), (int)(min_y * TILE_SIZE * ZOOM_LVL_BASE), (int)((max_x + 1) * TILE_SIZE * 2 * ZOOM_LVL_BASE), (int)((max_y + 1) * TILE_SIZE * ZOOM_LVL_BASE) }; } + +bool Plan::ValidateNewLine() +{ + extern bool AddPlanLine(PlanID plan, TileVector tiles); + + bool ret = false; + if (this->temp_line->tiles.size() > 1) { + this->temp_line->MarkDirty(); + this->last_tile = this->temp_line->tiles.back(); + this->SetVisibility(true, false); + TileVector tiles = std::move(this->temp_line->tiles); + this->temp_line->Clear(); + ret = AddPlanLine(this->index, std::move(tiles)); + } + return ret; +} diff --git a/src/plans_base.h b/src/plans_base.h index 00f7cc0a16..1e66bb366c 100644 --- a/src/plans_base.h +++ b/src/plans_base.h @@ -18,7 +18,6 @@ #include "map_func.h" #include "date_func.h" #include "viewport_func.h" -#include "core/endian_func.hpp" #include #include @@ -111,30 +110,6 @@ struct PlanLine { } } - TileIndex *Export(uint *buffer_length) - { - const uint cnt = (uint) this->tiles.size(); - const uint datalen = sizeof(TileIndex) * cnt; - TileIndex *buffer = (TileIndex *) malloc(datalen); - if (buffer) { - for (uint i = 0; i < cnt; i++) { - buffer[i] = TO_LE32(this->tiles[i]); - } - if (buffer_length) *buffer_length = datalen; - } - return buffer; - } - - bool Import(const TileIndex* data, const uint data_length) - { - for (uint i = data_length; i != 0; i--, data++) { - TileIndex t = FROM_LE32(*data); - if (t >= MapSize()) return false; - this->tiles.push_back(t); - } - return true; - } - void AddLineToCalculateCentreTile(uint64 &x, uint64 &y, uint32 &count) const { for (size_t i = 0; i < this->tiles.size(); i++) { @@ -226,24 +201,7 @@ struct Plan : PlanPool::PoolItem<&_plan_pool> { return this->temp_line->AppendTile(tile); } - bool ValidateNewLine() - { - bool ret = false; - if (this->temp_line->tiles.size() > 1) { - uint buffer_length = 0; - const TileIndex *buffer = this->temp_line->Export(&buffer_length); - uint tiles = (uint)this->temp_line->tiles.size(); - this->temp_line->MarkDirty(); - this->last_tile = this->temp_line->tiles.back(); - this->temp_line->Clear(); - if (buffer) { - this->SetVisibility(true, false); - ret = DoCommandPEx(0, this->index, tiles, 0, CMD_ADD_PLAN_LINE, nullptr, (const char *) buffer, buffer_length); - free(buffer); - } - } - return ret; - } + bool ValidateNewLine(); bool IsListable() { diff --git a/src/plans_cmd.cpp b/src/plans_cmd.cpp index 7ce8efb179..7e1e7e5dd1 100644 --- a/src/plans_cmd.cpp +++ b/src/plans_cmd.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "command_func.h" +#include "command_aux.h" #include "plans_base.h" #include "plans_func.h" #include "window_func.h" @@ -43,6 +44,36 @@ CommandCost CmdAddPlan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2 return CommandCost(); } +struct PlanLineCmdData : public CommandAuxiliarySerialisable { + TileVector tiles; + + virtual void Serialise(CommandSerialisationBuffer &buffer) const override + { + buffer.Send_uint32((uint32)this->tiles.size()); + for (TileIndex t : this->tiles) { + buffer.Send_uint32(t); + } + } + + CommandCost Deserialise(CommandDeserialisationBuffer &buffer) + { + uint32 size = buffer.Recv_uint32(); + if (!buffer.CanRecvBytes(size * 4)) return CMD_ERROR; + this->tiles.resize(size); + for (uint i = 0; i < size; i++) { + this->tiles[i] = buffer.Recv_uint32(); + } + return CommandCost(); + } +}; + +bool AddPlanLine(PlanID plan, TileVector tiles) +{ + PlanLineCmdData data; + data.tiles = std::move(tiles); + return DoCommandPEx(0, plan, 0, 0, CMD_ADD_PLAN_LINE, nullptr, nullptr, &data); +} + /** * Create a new line in a plan. * @param tile unused @@ -50,25 +81,25 @@ CommandCost CmdAddPlan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2 * @param p1 plan id * @param p2 number of nodes * @param text list of tile indexes that compose the line - * @param binary_length binary length of text + * @param aux_data auxiliary data * @return the cost of this operation or an error */ -CommandCost CmdAddPlanLine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdAddPlanLine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { Plan *p = Plan::GetIfValid(p1); if (p == nullptr) return CMD_ERROR; CommandCost ret = CheckOwnership(p->owner); if (ret.Failed()) return ret; - if (p2 > (MAX_CMD_TEXT_LENGTH / sizeof(TileIndex))) return_cmd_error(STR_ERROR_TOO_MANY_NODES); - if (!text || binary_length != p2 * 4) return CMD_ERROR; + + CommandAuxData data; + ret = data.Load(aux_data); + if (ret.Failed()) return ret; + + if (data->tiles.size() > (MAX_CMD_TEXT_LENGTH / sizeof(TileIndex))) return_cmd_error(STR_ERROR_TOO_MANY_NODES); if (flags & DC_EXEC) { PlanLine *pl = p->NewLine(); if (!pl) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_LINES); - if (!pl->Import((const TileIndex *) text, p2)) { - delete pl; - p->lines.pop_back(); - return CMD_ERROR; - } + pl->tiles = std::move(data->tiles); pl->UpdateVisualExtents(); if (p->IsListable()) { pl->SetVisibility(p->visible); diff --git a/src/schdispatch_cmd.cpp b/src/schdispatch_cmd.cpp index 8fb216bd6d..bfb87330fc 100644 --- a/src/schdispatch_cmd.cpp +++ b/src/schdispatch_cmd.cpp @@ -73,7 +73,7 @@ CommandCost CmdScheduledDispatch(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdScheduledDispatchAdd(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdScheduledDispatchAdd(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { VehicleID veh = GB(p1, 0, 20); uint schedule_index = GB(p1, 20, 12); @@ -185,7 +185,7 @@ CommandCost CmdScheduledDispatchSetDuration(TileIndex tile, DoCommandFlag flags, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdScheduledDispatchSetStartDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdScheduledDispatchSetStartDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { VehicleID veh = GB(p1, 0, 20); uint schedule_index = GB(p1, 20, 12); @@ -330,7 +330,7 @@ CommandCost CmdScheduledDispatchClear(TileIndex tile, DoCommandFlag flags, uint3 * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdScheduledDispatchAddNewSchedule(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdScheduledDispatchAddNewSchedule(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { VehicleID veh = GB(p1, 0, 20); diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index fefadb7bfa..fff867ed65 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -313,7 +313,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() return GetStorage()->callback_value[index]; } -/* static */ bool ScriptObject::DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd, const char *text, uint32 binary_length, Script_SuspendCallbackProc *callback) +/* static */ bool ScriptObject::DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd, const char *text, const CommandAuxiliaryBase *aux_data, 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."); @@ -325,7 +325,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() } std::string text_validated; - if (binary_length == 0 && !StrEmpty(text) && (GetCommandFlags(cmd) & CMD_STR_CTRL) == 0) { + if (!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. */ text_validated = text; @@ -349,7 +349,7 @@ ScriptObject::ActiveInstance::~ActiveInstance() if (!estimate_only && _networking && !_generating_world) SetLastCommand(tile, p1, p2, p3, cmd); /* Try to perform the command. */ - CommandCost res = ::DoCommandPScript(tile, p1, p2, p3, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, text, false, estimate_only, binary_length); + CommandCost res = ::DoCommandPScript(tile, p1, p2, p3, cmd, (_networking && !_generating_world) ? ScriptObject::GetActiveInstance()->GetDoCommandCallback() : nullptr, text, false, estimate_only, aux_data); /* We failed; set the error and bail out */ if (res.Failed()) { diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index a5dedd267d..f0e921dcee 100644 --- a/src/script/api/script_object.hpp +++ b/src/script/api/script_object.hpp @@ -18,6 +18,8 @@ #include "../script_suspend.hpp" #include "../squirrel.hpp" +struct CommandAuxiliaryBase; + /** * The callback function for Mode-classes. */ @@ -69,7 +71,7 @@ protected: /** * Executes a raw DoCommand for the script. */ - 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 DoCommandEx(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint cmd, const char *text = nullptr, const CommandAuxiliaryBase *aux_data = nullptr, Script_SuspendCallbackProc *callback = nullptr); static bool DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text = nullptr, Script_SuspendCallbackProc *callback = nullptr) { diff --git a/src/settings.cpp b/src/settings.cpp index 92f46e5d0c..4e8c08b09c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2647,7 +2647,7 @@ void SyncCompanySettings() if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; uint32 old_value = (uint32)sd->AsIntSetting()->Read(old_object); uint32 new_value = (uint32)sd->AsIntSetting()->Read(new_object); - if (old_value != new_value) NetworkSendCommand(0, 0, new_value, 0, CMD_CHANGE_COMPANY_SETTING, nullptr, sd->name, _local_company, 0); + if (old_value != new_value) NetworkSendCommand(0, 0, new_value, 0, CMD_CHANGE_COMPANY_SETTING, nullptr, sd->name, _local_company, nullptr); } } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index ebb648b544..67e1b394cb 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2087,7 +2087,7 @@ static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID statio * @param text Unused. * @return The cost of this operation or an error. */ -CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { bool type = HasBit(p2, 0); bool is_drive_through = HasBit(p2, 1); diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 3e91572647..adb119b327 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -162,7 +162,7 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint32 val, * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { VehicleID veh = GB(p1, 0, 20); diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 10e0a693e0..2e713b9000 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -199,7 +199,7 @@ extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec * @param text unused * @return the cost of this operation or an error */ -CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { /* Unpack parameters */ Axis axis = Extract(p1); @@ -344,7 +344,7 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint * @param text Unused. * @return The cost of this operation or an error. */ -CommandCost CmdBuildRoadWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, uint32 binary_length) +CommandCost CmdBuildRoadWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data) { StationID station_to_join = GB(p2, 16, 16); byte width = GB(p1, 0, 8);