Changeset - r28362:23e5c9d6b27d
[Not reviewed]
master
0 3 0
Charles Pigott - 11 months ago 2023-12-30 17:46:32
charlespigott@googlemail.com
Fix: Compilation with DEBUG_DUMP_COMMANDS enabled (#11607)
3 files changed with 18 insertions and 12 deletions:
0 comments (0 inline, 0 general)
src/command.cpp
Show inline comments
 
@@ -269,15 +269,15 @@ void CommandHelperBase::InternalPostResu
 
		 * concept of cost, so don't show it there either. */
 
		ShowCostOrIncomeAnimation(x, y, GetSlopePixelZ(x, y), res.GetCost());
 
	}
 
}
 

	
 
/** Helper to make a desync log for a command. */
 
void CommandHelperBase::LogCommandExecution(Commands cmd, StringID err_message, TileIndex tile, const CommandDataBuffer &args, bool failed)
 
void CommandHelperBase::LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
 
{
 
	Debug(desync, 1, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {:06x}; {} ({})", failed ? "cmdf" : "cmd", TimerGameCalendar::date, TimerGameCalendar::date_fract, (int)_current_company, cmd, err_message, tile, FormatArrayAsHex(args), GetCommandName(cmd));
 
	Debug(desync, 1, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {} ({})", failed ? "cmdf" : "cmd", (uint32_t)TimerGameCalendar::date.base(), TimerGameCalendar::date_fract, (int)_current_company, cmd, err_message, FormatArrayAsHex(args), GetCommandName(cmd));
 
}
 

	
 
/**
 
 * Prepare for the test run of a command proc call.
 
 * @param cmd_flags Command flags.
 
 * @param[in,out] cur_company Backup of current company at start of command execution.
src/command_func.h
Show inline comments
 
@@ -99,13 +99,13 @@ protected:
 
	static void InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test);
 
	static std::tuple<bool, bool, bool> InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command);
 
	static void InternalPostResult(const CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd);
 
	static bool InternalExecutePrepTest(CommandFlags cmd_flags, TileIndex tile, Backup<CompanyID> &cur_company);
 
	static std::tuple<bool, bool, bool> InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, Backup<CompanyID> &cur_company);
 
	static CommandCost InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company);
 
	static void LogCommandExecution(Commands cmd, StringID err_message, TileIndex tile, const CommandDataBuffer &args, bool failed);
 
	static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed);
 
};
 

	
 
/**
 
 * Templated wrapper that exposes the command parameter arguments
 
 * for the various Command::Do/Post calls.
 
 * @tparam Tcmd The command-id to execute.
 
@@ -382,13 +382,13 @@ protected:
 
		/* Test the command. */
 
		DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
 
		Tret res = std::apply(CommandTraits<Tcmd>::proc, std::tuple_cat(std::make_tuple(flags), args));
 

	
 
		auto [exit_test, desync_log, send_net] = InternalExecuteValidateTestAndPrepExec(ExtractCommandCost(res), cmd_flags, estimate_only, network_command, cur_company);
 
		if (exit_test) {
 
			if (desync_log) LogCommandExecution(Tcmd, err_message, tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args), true);
 
			if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter<CommandDataBuffer>::FromValue(args), true);
 
			cur_company.Restore();
 
			return res;
 
		}
 

	
 
		/* If we are in network, and the command is not from the network
 
		 * send it to the command-queue and abort execution. */
 
@@ -400,13 +400,13 @@ protected:
 
			 * This way it's not handled by DoCommand and only the
 
			 * actual execution of the command causes messages. Also
 
			 * reset the storages as we've not executed the command. */
 
			return {};
 
		}
 

	
 
		if (desync_log) LogCommandExecution(Tcmd, err_message, tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args), false);
 
		if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter<CommandDataBuffer>::FromValue(args), false);
 

	
 
		/* Actually try and execute the command. */
 
		Tret res2 = std::apply(CommandTraits<Tcmd>::proc, std::tuple_cat(std::make_tuple(flags | DC_EXEC), args));
 

	
 
		/* Convention: If the second result element is of type Money,
 
		 * this is the additional cash required for the command. */
src/network/network.cpp
Show inline comments
 
@@ -1052,27 +1052,27 @@ void NetworkGameLoop()
 
			}
 
		}
 

	
 
#ifdef DEBUG_DUMP_COMMANDS
 
		/* Loading of the debug commands from -ddesync>=1 */
 
		static FILE *f = FioFOpenFile("commands.log", "rb", SAVE_DIR);
 
		static Date next_date = 0;
 
		static TimerGameCalendar::Date next_date(0);
 
		static uint32_t next_date_fract;
 
		static CommandPacket *cp = nullptr;
 
		static bool check_sync_state = false;
 
		static uint32_t sync_state[2];
 
		if (f == nullptr && next_date == 0) {
 
			Debug(desync, 0, "Cannot open commands.log");
 
			next_date = 1;
 
			next_date = TimerGameCalendar::Date(1);
 
		}
 

	
 
		while (f != nullptr && !feof(f)) {
 
			if (TimerGameCalendar::date == next_date && TimerGameCalendar::date_fract == next_date_fract) {
 
				if (cp != nullptr) {
 
					NetworkSendCommand(cp->cmd, cp->err_msg, nullptr, cp->company, cp->data);
 
					Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {:06x}; {} ({})", TimerGameCalendar::date, TimerGameCalendar::date_fract, (int)_current_company, cp->cmd, cp->tile, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd));
 
					Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {} ({})", TimerGameCalendar::date, TimerGameCalendar::date_fract, (int)_current_company, cp->cmd, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd));
 
					delete cp;
 
					cp = nullptr;
 
				}
 
				if (check_sync_state) {
 
					if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) {
 
						Debug(desync, 0, "Sync check: {:08x}; {:02x}; match", TimerGameCalendar::date, TimerGameCalendar::date_fract);
 
@@ -1106,38 +1106,44 @@ void NetworkGameLoop()
 
				p += 5;
 
				if (*p == ' ') p++;
 
				cp = new CommandPacket();
 
				int company;
 
				uint cmd;
 
				char buffer[256];
 
				int ret = sscanf(p, "%x; %x; %x; %x; %x; %x; %255s", &next_date, &next_date_fract, &company, &cmd, &cp->err_msg, &cp->tile, buffer);
 
				uint32_t next_date_raw;
 
				int ret = sscanf(p, "%x; %x; %x; %x; %x; %255s", &next_date_raw, &next_date_fract, &company, &cmd, &cp->err_msg, buffer);
 
				assert(ret == 6);
 
				next_date = TimerGameCalendar::Date((int32_t)next_date_raw);
 
				cp->company = (CompanyID)company;
 
				cp->cmd = (Commands)cmd;
 

	
 
				/* Parse command data. */
 
				std::vector<byte> args;
 
				size_t arg_len = strlen(buffer);
 
				for (size_t i = 0; i + 1 < arg_len; i += 2) {
 
					byte e = 0;
 
					std::from_chars(buffer + i, buffer + i + 1, e, 16);
 
					std::from_chars(buffer + i, buffer + i + 2, e, 16);
 
					args.emplace_back(e);
 
				}
 
				cp->data = args;
 
			} 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, "%x; %x", &next_date, &next_date_fract);
 
				uint32_t next_date_raw;
 
				int ret = sscanf(p + 6, "%x; %x", &next_date_raw, &next_date_fract);
 
				next_date = TimerGameCalendar::Date((int32_t)next_date_raw);
 
				assert(ret == 2);
 
				Debug(desync, 0, "Injecting pause for join at {:08x}:{:02x}; please join when paused", next_date, next_date_fract);
 
				cp = new CommandPacket();
 
				cp->company = COMPANY_SPECTATOR;
 
				cp->cmd = CMD_PAUSE;
 
				cp->data = EndianBufferWriter<>::FromValue(CommandTraits<CMD_PAUSE>::Args{ PM_PAUSED_NORMAL, true });
 
				_ddc_fastforward = false;
 
			} else if (strncmp(p, "sync: ", 6) == 0) {
 
				int ret = sscanf(p + 6, "%x; %x; %x; %x", &next_date, &next_date_fract, &sync_state[0], &sync_state[1]);
 
				uint32_t next_date_raw;
 
				int ret = sscanf(p + 6, "%x; %x; %x; %x", &next_date_raw, &next_date_fract, &sync_state[0], &sync_state[1]);
 
				next_date = TimerGameCalendar::Date((int32_t)next_date_raw);
 
				assert(ret == 4);
 
				check_sync_state = true;
 
			} else if (strncmp(p, "msg: ", 5) == 0 || strncmp(p, "client: ", 8) == 0 ||
 
						strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0) {
 
				/* A message that is not very important to the log playback, but part of the log. */
 
#ifndef DEBUG_FAILED_DUMP_COMMANDS
0 comments (0 inline, 0 general)