// // CL_PredicMove // void CL_PredictMove (void) { if (noservermsgs) return; player_t *p = &consoleplayer(); if (!p->tic || !p->mo) return; // Save player angle, viewheight,deltaviewheight and jumpTics. // Will use it later to predict movements int buf = gametic%MAXSAVETICS; cl_angle[buf] = p->mo->angle; cl_pitch[buf] = p->mo->pitch; cl_viewheight[buf] = p->viewheight; cl_deltaviewheight[buf] = p->deltaviewheight; cl_jumpTics[buf] = p->jumpTics; cl_reactiontime[buf] = p->mo->reactiontime; // Disable sounds, etc, during prediction predicting = true; // Set predictable items to their last received positions CL_ResetPlayers(); CL_ResetSectors(); int predtic = gametic - MAXSAVETICS; if(predtic < 0) predtic = 0; // Predict each tic while(predtic < gametic) { CL_PredictPlayers(predtic); CL_PredictSectors(predtic); ++predtic; } predicting = false; CL_PredictPlayers(predtic); CL_PredictSectors(predtic); }
// // CL_PredictMove // void CL_PredictMove (void) { if (noservermsgs) return; player_t *p = &consoleplayer(); if (!p->tic || !p->mo) { if (!p->spectator) return; // Predict sectors for local player who is a spectator CL_ResetSectors(); int predtic = gametic - MAXSAVETICS; if(predtic < 0) predtic = 0; while(++predtic < gametic) { CL_PredictSectors(predtic); } return; } #ifdef _PRED_DBG fixed_t origx, origy, origz; #endif // Save player angle, viewheight,deltaviewheight and jumpTics. // Will use it later to predict movements int buf = gametic%MAXSAVETICS; cl_angle[buf] = p->mo->angle; cl_pitch[buf] = p->mo->pitch; cl_viewheight[buf] = p->viewheight; cl_deltaviewheight[buf] = p->deltaviewheight; cl_jumpTics[buf] = p->jumpTics; cl_reactiontime[buf] = p->mo->reactiontime; cl_waterlevel[buf] = p->mo->waterlevel; #ifdef _PRED_DBG // Backup original position origx = p->mo->x; origy = p->mo->y; origz = p->mo->z; #endif // Disable sounds, etc, during prediction predicting = true; // Set predictable items to their last received positions CL_ResetPlayers(); CL_ResetSectors(); int predtic = gametic - MAXSAVETICS; if(predtic < 0) predtic = 0; // Predict each tic while(++predtic < gametic) { CL_PredictPlayers(predtic); CL_PredictSectors(predtic); } predicting = false; CL_PredictPlayers(predtic); // [Russell] - I don't think we need to call this as DThinker::RunThinkers() // will already run the moving sector thinkers after prediction //CL_PredictSectors(predtic); #ifdef _PRED_DBG if ((origx == p->mo->x) && (origy == p->mo->y) && (origz == p->mo->z)) { Printf(PRINT_HIGH, "%d tics predicted\n", predtic); } else { Printf(PRINT_HIGH, "%d tics failed\n", predtic); } #endif }
// // CL_PredictWorld // // Main function for client-side prediction. // void CL_PredictWorld(void) { if (gamestate != GS_LEVEL) return; player_t *p = &consoleplayer(); if (!validplayer(*p) || !p->mo || noservermsgs || netdemo.isPaused()) return; // tenatively tell the netgraph that our prediction was successful netgraph.setMisprediction(false); if (consoleplayer_id != displayplayer_id) CL_PredictSpying(); // [SL] 2012-03-10 - Spectators can predict their position without server // correction. Handle them as a special case and leave. if (consoleplayer().spectator) { CL_PredictSpectator(); return; } if (p->tic <= 0) // No verified position from the server return; // Disable sounds, etc, during prediction predicting = true; // Figure out where to start predicting from int predtic = consoleplayer().tic > 0 ? consoleplayer().tic: 0; // Last position update from the server is too old! if (predtic < gametic - MAXSAVETICS) predtic = gametic - MAXSAVETICS; // Save a snapshot of the player's state before prediction PlayerSnapshot prevsnap(p->tic, p); cl_savedsnaps[gametic % MAXSAVETICS] = prevsnap; // Move sectors to the last position received from the server if (cl_predictsectors) CL_ResetSectors(); // Move the client to the last position received from the sever int snaptime = p->snapshots.getMostRecentTime(); PlayerSnapshot snap = p->snapshots.getSnapshot(snaptime); snap.toPlayer(p); if (cl_predictlocalplayer) { while (++predtic < gametic) { if (cl_predictsectors) CL_PredictSectors(predtic); CL_PredictLocalPlayer(predtic); } // If the player didn't just spawn or teleport, nudge the player from // his position last tic to this new corrected position. This smooths the // view when there's a misprediction. if (snap.isContinuous()) { PlayerSnapshot correctedprevsnap(p->tic, p); // Did we predict correctly? bool correct = (correctedprevsnap.getX() == prevsnap.getX()) && (correctedprevsnap.getY() == prevsnap.getY()) && (correctedprevsnap.getZ() == prevsnap.getZ()); if (!correct) { // Update the netgraph concerning our prediction's error netgraph.setMisprediction(true); // Lerp from the our previous position to the correct position PlayerSnapshot lerpedsnap = P_LerpPlayerPosition(prevsnap, correctedprevsnap, cl_prednudge); lerpedsnap.toPlayer(p); // [SL] 2012-04-26 - Snap directly to the corrected position in // the z direction. This prevents players from floating above // lifts when the lift height is mispredicted. p->mo->z = correctedprevsnap.getZ(); } } } predicting = false; // Run thinkers for current gametic if (cl_predictsectors) CL_PredictSectors(gametic); CL_PredictLocalPlayer(gametic); }