The main loop called from ttd.c * Here we also have to do StateGameLoop if needed! */
| 1093 | /* The main loop called from ttd.c |
| 1094 | * Here we also have to do StateGameLoop if needed! */ |
| 1095 | void NetworkGameLoop() |
| 1096 | { |
| 1097 | if (!_networking) return; |
| 1098 | |
| 1099 | if (!NetworkReceive()) return; |
| 1100 | |
| 1101 | if (_network_server) { |
| 1102 | /* Log the sync state to check for in-syncedness of replays. */ |
| 1103 | if (TimerGameEconomy::date_fract == 0) { |
| 1104 | /* We don't want to log multiple times if paused. */ |
| 1105 | static TimerGameEconomy::Date last_log; |
| 1106 | if (last_log != TimerGameEconomy::date) { |
| 1107 | Debug(desync, 1, "sync: {:08x}; {:02x}; {:08x}; {:08x}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _random.state[0], _random.state[1]); |
| 1108 | last_log = TimerGameEconomy::date; |
| 1109 | } |
| 1110 | } |
| 1111 | |
| 1112 | #ifdef DEBUG_DUMP_COMMANDS |
| 1113 | /* Loading of the debug commands from -ddesync>=1 */ |
| 1114 | static auto f = FioFOpenFile("commands.log", "rb", SAVE_DIR); |
| 1115 | static TimerGameEconomy::Date next_date(0); |
| 1116 | static uint32_t next_date_fract; |
| 1117 | static CommandPacket *cp = nullptr; |
| 1118 | static bool check_sync_state = false; |
| 1119 | static uint32_t sync_state[2]; |
| 1120 | if (!f.has_value() && next_date == 0) { |
| 1121 | Debug(desync, 0, "Cannot open commands.log"); |
| 1122 | next_date = TimerGameEconomy::Date(1); |
| 1123 | } |
| 1124 | |
| 1125 | while (f.has_value() && !feof(*f)) { |
| 1126 | if (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract == next_date_fract) { |
| 1127 | if (cp != nullptr) { |
| 1128 | NetworkSendCommand(cp->cmd, cp->err_msg, nullptr, cp->company, cp->data); |
| 1129 | Debug(desync, 0, "Injecting: {:08x}; {:02x}; {:02x}; {:08x}; {} ({})", TimerGameEconomy::date, TimerGameEconomy::date_fract, _current_company.base(), cp->cmd, FormatArrayAsHex(cp->data), GetCommandName(cp->cmd)); |
| 1130 | delete cp; |
| 1131 | cp = nullptr; |
| 1132 | } |
| 1133 | if (check_sync_state) { |
| 1134 | if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) { |
| 1135 | Debug(desync, 0, "Sync check: {:08x}; {:02x}; match", TimerGameEconomy::date, TimerGameEconomy::date_fract); |
| 1136 | } else { |
| 1137 | Debug(desync, 0, "Sync check: {:08x}; {:02x}; mismatch expected {{{:08x}, {:08x}}}, got {{{:08x}, {:08x}}}", |
| 1138 | TimerGameEconomy::date, TimerGameEconomy::date_fract, sync_state[0], sync_state[1], _random.state[0], _random.state[1]); |
| 1139 | NOT_REACHED(); |
| 1140 | } |
| 1141 | check_sync_state = false; |
| 1142 | } |
| 1143 | } |
| 1144 | |
| 1145 | /* Skip all entries in the command-log till we caught up with the current game again. */ |
| 1146 | if (TimerGameEconomy::date > next_date || (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract > next_date_fract)) { |
| 1147 | Debug(desync, 0, "Skipping to next command at {:08x}:{:02x}", next_date, next_date_fract); |
| 1148 | if (cp != nullptr) { |
| 1149 | delete cp; |
| 1150 | cp = nullptr; |
| 1151 | } |
| 1152 | check_sync_state = false; |
no test coverage detected