// Checks if we need to ask the server for a re-request of the current download // chunk void CL_DownloadTicker() { dtime_t diff = 0; if(gamestate != GS_DOWNLOAD || download.filename.empty()) { return; } if (download.timeout) { // Calculate how many seconds have elapsed since the last server // response diff = I_GetTime() - download.timeout; if (diff) diff /= I_ConvertTimeFromMs(1000); } else { download.timeout = I_GetTime(); return; } if (diff >= 3) { DPrintf("No response from server for %d seconds, re-requesting\n", diff); MSG_WriteMarker(&net_buffer, clc_wantwad); MSG_WriteString(&net_buffer, download.filename.c_str()); MSG_WriteString(&net_buffer, download.md5.c_str()); MSG_WriteLong(&net_buffer, download.got_bytes); NET_SendPacket(net_buffer, serveraddr); download.timeout = 0; ++download.retrycount; } if (download.retrycount >= 5) { Printf(PRINT_HIGH, "Server hasn't responded to download re-requests, aborting\n"); download.retrycount = 0; download.timeout = 0; CL_QuitNetGame(); gamestate = GS_STARTUP; } }
// // D_RunTics // // The core of the main game loop. // This loop allows the game simulation timing to be decoupled from the renderer // timing. If the the user selects a capped framerate and isn't using the // -timedemo parameter, both the simulation and render functions will be called // TICRATE times a second. If the framerate is uncapped, the simulation function // will still be called TICRATE times a second but the render function will // be called as often as possible. After each iteration through the loop, // the program yields briefly to the operating system. // void D_RunTics(void (*sim_func)(), void(*render_func)()) { static const uint64_t sim_dt = I_ConvertTimeFromMs(1000) / TICRATE; static uint64_t previous_time = I_GetTime(); uint64_t current_time = I_GetTime(); // reset the rendering interpolation render_lerp_amount = FRACUNIT; static uint64_t accumulator = sim_dt; if (!timingdemo) // run simulation function at 35Hz? { // Run upto 4 simulation frames. Limit the number because there's already a // slowdown and running more will only make things worse. accumulator += MIN(current_time - previous_time, 4 * sim_dt); // calculate how late the start of the frame is (for debugging) uint64_t late_time_ms = current_time - previous_time > sim_dt ? I_ConvertTimeToMs(current_time - previous_time - sim_dt) : 0; if (late_time_ms > 2) DPrintf("Warning: frame start is %ums late!\n", late_time_ms); while (accumulator >= sim_dt) { sim_func(); accumulator -= sim_dt; } // Use linear interpolation for rendering entities if the renderer // framerate is not synced with the physics frequency. if (maxfps != TICRATE && !(paused || menuactive || step_mode)) render_lerp_amount = (fixed_t)(accumulator * FRACUNIT / sim_dt); } else // run simulation function as fast as possible { sim_func(); accumulator = 0; } render_func(); static float previous_maxfps = -1; if (!timingdemo && capfps) // render at a capped framerate? { static uint64_t render_dt, previous_block; uint64_t current_block; // The capped framerate has changed so recalculate some stuff if (maxfps != previous_maxfps) { render_dt = I_ConvertTimeFromMs(1000) / maxfps; previous_block = current_time / render_dt; } // With capped framerates, frames are rendered within fixed blocks of time // and at the end of a frame, sleep until the start of the next block. do I_Yield(); while ( (current_block = I_GetTime() / render_dt) <= previous_block); previous_block = current_block; previous_maxfps = maxfps; } else if (!timingdemo) // render at an unlimited framerate (but still yield) { // sleep for 1ms to allow the operating system some time I_Yield(); previous_maxfps = -1; } previous_time = current_time; }