diff --git a/src/date.cpp b/src/date.cpp --- a/src/date.cpp +++ b/src/date.cpp @@ -13,6 +13,9 @@ #include "network/network_server.h" #include "functions.h" #include "currency.h" +#ifdef DEBUG_DUMP_COMMANDS +#include "saveload.h" +#endif Year _cur_year; Month _cur_month; @@ -259,6 +262,12 @@ void IncreaseDate() /* yes, call various monthly loops */ if (_game_mode != GM_MENU) { +#ifdef DEBUG_DUMP_COMMANDS + char name[MAX_PATH]; + snprintf(name, lengthof(name), "dmp_cmds_%d.sav", _date); + SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR); + debug_dump_commands("ddc:save:%s\n", name); +#endif /* DUMP_COMMANDS */ if (_opt.autosave != 0 && (_cur_month % _autosave_months[_opt.autosave]) == 0) { _do_autosave = true; RedrawAutosave(); diff --git a/src/network/network.cpp b/src/network/network.cpp --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -37,6 +37,7 @@ #include "../console.h" /* IConsoleCmdExec */ #include /* va_list */ #include "../md5.h" +#include "../fileio.h" /* Check whether NETWORK_NUM_LANDSCAPES is still in sync with NUM_LANDSCAPE */ assert_compile((int)NETWORK_NUM_LANDSCAPES == (int)NUM_LANDSCAPE); @@ -195,6 +196,9 @@ void CDECL NetworkTextMessage(NetworkAct break; } +#ifdef DEBUG_DUMP_COMMANDS + debug_dump_commands("ddc:cmsg:%d;%d;%s\n", _date, _date_fract, message); +#endif /* DUMP_COMMANDS */ IConsolePrintF(color, "%s", message); AddTextMessage(color, duration, "%s", message); } @@ -1235,6 +1239,9 @@ static bool NetworkDoClientLoop() if (_sync_seed_1 != _random_seeds[0][0]) { #endif NetworkError(STR_NETWORK_ERR_DESYNC); +#ifdef DEBUG_DUMP_COMMANDS + debug_dump_commands("ddc:serr:%d;%d\n", _date, _date_fract); +#endif /* DUMP_COMMANDS */ DEBUG(net, 0, "Sync error detected!"); NetworkClientError(NETWORK_RECV_STATUS_DESYNC, DEREF_CLIENT(0)); return false; @@ -1280,6 +1287,37 @@ void NetworkGameLoop() if (!NetworkReceive()) return; if (_network_server) { +#ifdef DEBUG_DUMP_COMMANDS + static FILE *f = FioFOpenFile("commands.log", "rb", SAVE_DIR); + static Date next_date = 0; + static uint32 next_date_fract; + static CommandPacket *cp = NULL; + if (f == NULL && next_date == 0) { + printf("Cannot open commands.log\n"); + next_date = 1; + } + + while (f != NULL && !feof(f)) { + if (cp != NULL && _date == next_date && _date_fract == next_date_fract) { + _current_player = cp->player; + _cmd_text = cp->text; + DoCommandP(cp->tile, cp->p1, cp->p2, NULL, cp->cmd); + free(cp); + cp = NULL; + } + + if (cp != NULL) break; + + char buff[4096]; + if (fgets(buff, lengthof(buff), f) == NULL) break; + if (strncmp(buff, "ddc:cmd:", 8) != 0) continue; + cp = MallocT(1); + int player; + sscanf(&buff[8], "%d;%d;%d;%d;%d;%d;%d;%s", &next_date, &next_date_fract, &player, &cp->tile, &cp->p1, &cp->p2, &cp->cmd, cp->text); + cp->player = (Owner)player; + } +#endif /* DUMP_COMMANDS */ + bool send_frame = false; // We first increase the _frame_counter @@ -1436,4 +1474,18 @@ bool IsNetworkCompatibleVersion(const ch strncmp(_openttd_revision, other, NETWORK_REVISION_LENGTH - 1) == 0; } +#ifdef DEBUG_DUMP_COMMANDS +void CDECL debug_dump_commands(const char *s, ...) +{ + static FILE *f = FioFOpenFile("commands-out.log", "wb", SAVE_DIR); + if (f == NULL) return; + + va_list va; + va_start(va, s); + vfprintf(f, s, va); + va_end(va); + + fflush(f); +} +#endif /* DEBUG_DUMP_COMMANDS */ #endif /* ENABLE_NETWORK */ diff --git a/src/network/network.h b/src/network/network.h --- a/src/network/network.h +++ b/src/network/network.h @@ -20,6 +20,17 @@ // nothing will happen. //#define ENABLE_NETWORK_SYNC_EVERY_FRAME +/* + * Dumps all commands that are sent/received to stderr and saves every month. + * This log can become quite large over time; say in the order of two to three + * times the bandwidth used for network games. + */ +//#define DEBUG_DUMP_COMMANDS + +#ifdef DEBUG_DUMP_COMMANDS +void CDECL debug_dump_commands(const char *s, ...); +#endif /* DEBUG_DUMP_COMMANDS */ + // In theory sending 1 of the 2 seeds is enough to check for desyncs // so in theory, this next define can be left off. //#define NETWORK_SEND_DOUBLE_SEED diff --git a/src/network/network_data.cpp b/src/network/network_data.cpp --- a/src/network/network_data.cpp +++ b/src/network/network_data.cpp @@ -97,6 +97,11 @@ void NetworkExecuteCommand(CommandPacket DEBUG(net, 0, "Received out-of-bounds callback (%d)", cp->callback); cp->callback = 0; } + +#ifdef DEBUG_DUMP_COMMANDS + debug_dump_commands("ddc:cmd:%d;%d;%d;%d;%d;%d;%d;%s\n", _date, _date_fract, (int)cp->player, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text); +#endif /* DUMP_COMMANDS */ + DoCommandP(cp->tile, cp->p1, cp->p2, _callback_table[cp->callback], cp->cmd | CMD_NETWORK_COMMAND); } diff --git a/src/saveload.cpp b/src/saveload.cpp --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -1677,6 +1677,9 @@ SaveOrLoadResult SaveOrLoad(const char * } } else { /* LOAD game */ assert(mode == SL_LOAD); +#ifdef DEBUG_DUMP_COMMANDS + debug_dump_commands("ddc:load:%s\n", filename); +#endif /* DUMP_COMMANDS */ if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);