From 733b2e6b3b35994fc62b16bacede093184680231 Mon Sep 17 00:00:00 2001 From: g-cont Date: Thu, 9 Jul 2015 00:00:00 +0300 Subject: [PATCH] 09 Jul 2015 --- engine/client/cl_frame.c | 21 +--- engine/client/cl_main.c | 6 +- engine/client/cl_parse.c | 25 +++++ engine/client/cl_pmove.c | 232 ++++++++++++++++++++++++--------------- engine/client/client.h | 6 +- engine/common/build.c | 2 +- engine/common/common.h | 1 + engine/server/sv_save.c | 1 + 8 files changed, 182 insertions(+), 112 deletions(-) diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index 25b66784..7b3a8a91 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -38,7 +38,7 @@ qboolean CL_IsPredicted( void ) if( !cl_predict->integer || !cl.frame.valid ) return false; - if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence ) >= ( CL_UPDATE_BACKUP - 1 )) + if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= ( CL_UPDATE_BACKUP - 1 )) return false; return true; @@ -810,23 +810,7 @@ void CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) } // update local player states - if( player != NULL ) - { - entity_state_t *ps, *pps; - clientdata_t *pcd, *ppcd; - weapon_data_t *wd, *pwd; - - pps = &player->curstate; - ppcd = &newframe->local.client; - pwd = newframe->local.weapondata; - - ps = &cl.predict[cl.predictcount & CL_UPDATE_MASK].playerstate; - pcd = &cl.predict[cl.predictcount & CL_UPDATE_MASK].client; - wd = cl.predict[cl.predictcount & CL_UPDATE_MASK].weapondata; - - clgame.dllFuncs.pfnTxferPredictionData( ps, pps, pcd, ppcd, wd, pwd ); - clgame.dllFuncs.pfnTxferLocalOverrides( &player->curstate, pcd ); - } + clgame.dllFuncs.pfnTxferLocalOverrides( &player->curstate, &newframe->local.client ); // update state for all players for( i = 0; i < cl.maxclients; i++ ) @@ -838,7 +822,6 @@ void CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) } cl.frame = *newframe; - cl.predict[cl.predictcount & CL_UPDATE_MASK] = cl.frame.local; } /* diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 7fe77788..55f532e8 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -337,8 +337,12 @@ void CL_CreateCmd( void ) // so don't overwrite them if( !cls.demoplayback ) { - cl.refdef.cmd = &cl.cmds[cls.netchan.outgoing_sequence & CL_UPDATE_MASK]; + int frame = cls.netchan.outgoing_sequence & CL_UPDATE_MASK; + + cl.refdef.cmd = &cl.cmds[frame]; *cl.refdef.cmd = cmd; + + cl.runfuncs[frame] = TRUE; } } diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 558dfd9e..dafa6dcb 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -712,7 +712,32 @@ void CL_ParseClientData( sizebuf_t *msg ) frame->time = cl.mtime[0]; // mark network received time frame->receivedtime = host.realtime; // time now that we are parsing. + if( cl.last_command_ack != -1 ) + { + int last_predicted; + entity_state_t * ps; + entity_state_t * pps; + clientdata_t * pcd; + clientdata_t * ppcd; + weapon_data_t * wd; + weapon_data_t * pwd; + + last_predicted = ( cl.last_incoming_sequence + ( + cls.netchan.incoming_acknowledged - cl.last_command_ack)) & CL_UPDATE_MASK; + + pps = &cl.predict[last_predicted].playerstate; + ppcd = &cl.predict[last_predicted].client; + pwd = cl.predict[last_predicted].weapondata; + + ps = &frame->playerstate[cl.playernum]; + pcd = &frame->local.client; + wd = frame->local.weapondata; + + clgame.dllFuncs.pfnTxferPredictionData( ps, pps, pcd, ppcd, wd, pwd ); + } + // do this after all packets read for this frame? + cl.last_command_ack = cls.netchan.incoming_acknowledged; cl.last_incoming_sequence = cls.netchan.incoming_sequence; if( hltv->integer ) return; // clientdata for spectators ends here diff --git a/engine/client/cl_pmove.c b/engine/client/cl_pmove.c index cd7e3080..ddab9808 100644 --- a/engine/client/cl_pmove.c +++ b/engine/client/cl_pmove.c @@ -704,80 +704,132 @@ void CL_SetSolidEntities( void ) } } -void CL_SetupPMove( playermove_t *pmove, clientdata_t *cd, entity_state_t *state, usercmd_t *ucmd ) -{ - pmove->player_index = cl.playernum; - pmove->multiplayer = (cl.maxclients > 1) ? true : false; - pmove->time = cl.time; // probably never used - VectorCopy( cd->origin, pmove->origin ); - VectorCopy( cl.refdef.cl_viewangles, pmove->angles ); - VectorCopy( cl.refdef.cl_viewangles, pmove->oldangles ); - VectorCopy( cd->velocity, pmove->velocity ); - VectorCopy( state->basevelocity, pmove->basevelocity ); - VectorCopy( cd->view_ofs, pmove->view_ofs ); - VectorClear( pmove->movedir ); - pmove->flDuckTime = cd->flDuckTime; - pmove->bInDuck = cd->bInDuck; - pmove->usehull = (cd->flags & FL_DUCKING) ? 1 : 0; // reset hull - pmove->flTimeStepSound = cd->flTimeStepSound; - pmove->iStepLeft = state->iStepLeft; - pmove->flFallVelocity = state->flFallVelocity; - pmove->flSwimTime = cd->flSwimTime; - VectorCopy( cd->punchangle, pmove->punchangle ); - pmove->flSwimTime = cd->flSwimTime; - pmove->flNextPrimaryAttack = 0.0f; // not used by PM_ code - pmove->effects = state->effects; - pmove->flags = cd->flags; - pmove->gravity = state->gravity; - pmove->friction = state->friction; - pmove->oldbuttons = state->oldbuttons; - pmove->waterjumptime = cd->waterjumptime; - pmove->dead = (cd->health <= 0.0f ) ? true : false; - pmove->deadflag = cd->deadflag; - pmove->spectator = (state->spectator != 0); - pmove->movetype = state->movetype; - pmove->onground = -1; // will be set by PM_ code - pmove->waterlevel = cd->waterlevel; - pmove->watertype = cd->watertype; - pmove->maxspeed = clgame.movevars.maxspeed; - pmove->clientmaxspeed = cd->maxspeed; - pmove->iuser1 = cd->iuser1; - pmove->iuser2 = cd->iuser2; - pmove->iuser3 = cd->iuser3; - pmove->iuser4 = cd->iuser4; - pmove->fuser1 = cd->fuser1; - pmove->fuser2 = cd->fuser2; - pmove->fuser3 = cd->fuser3; - pmove->fuser4 = cd->fuser4; - VectorCopy( cd->vuser1, pmove->vuser1 ); - VectorCopy( cd->vuser2, pmove->vuser2 ); - VectorCopy( cd->vuser3, pmove->vuser3 ); - VectorCopy( cd->vuser4, pmove->vuser4 ); - pmove->cmd = *ucmd; // setup current cmds - - Q_strncpy( pmove->physinfo, cd->physinfo, MAX_INFO_STRING ); -} - /* -=========== -CL_PostRunCmd +================= +CL_RunUsercmd -Done after running a player command. -=========== +Runs prediction code for user cmd +================= */ -void CL_PostRunCmd( usercmd_t *ucmd, int random_seed ) +void CL_RunUsercmd(local_state_t * from, local_state_t * to, usercmd_t * u, qboolean runfuncs, double * pfElapsed, unsigned int random_seed) { - local_state_t *from, *to; + usercmd_t cmd; + entity_state_t * fs; + entity_state_t * ts; + clientdata_t * fcd; + clientdata_t * tcd; + playermove_t *pmove = clgame.pmove; - // TODO: write real predicting code + while (u->msec > 50) + { + local_state_t temp; + usercmd_t split; - from = &cl.predict[cl.predictcount & CL_UPDATE_MASK]; - to = &cl.predict[(cl.predictcount + 1) & CL_UPDATE_MASK]; + split = *u; + split.msec /= 2.0; + CL_RunUsercmd(from, &temp, &split, runfuncs, pfElapsed, random_seed); + from = &temp; + u = &split; + } + + cmd = *u; *to = *from; - clgame.dllFuncs.pfnPostRunCmd( from, to, ucmd, clgame.pmove->runfuncs, cl.time, random_seed ); - cl.predictcount++; + fs = &from->playerstate; + fcd = &from->client; + ts = &to->playerstate; + tcd = &to->client; + + pmove->time = *pfElapsed * 1000.0; + pmove->server = 0; + pmove->multiplayer = (cl.maxclients > 1); + pmove->runfuncs = runfuncs; + pmove->frametime = cmd.msec / 1000.0; + pmove->player_index = fs->number - 1; + pmove->flags = fcd->flags; + pmove->bInDuck = fcd->bInDuck; + pmove->flTimeStepSound = fcd->flTimeStepSound; + pmove->flDuckTime = fcd->flDuckTime; + pmove->flSwimTime = fcd->flSwimTime; + pmove->waterjumptime = fcd->waterjumptime; + pmove->waterlevel = fcd->waterlevel; + pmove->watertype = fcd->watertype; + pmove->onground = fcd->flags & FL_ONGROUND; + pmove->deadflag = fcd->deadflag; + VectorCopy(fcd->velocity, pmove->velocity); + VectorCopy(fcd->view_ofs, pmove->view_ofs); + VectorCopy(fs->origin, pmove->origin); + VectorCopy(fs->basevelocity, pmove->basevelocity); + VectorCopy(fcd->punchangle, pmove->punchangle); + VectorCopy(fs->angles, pmove->angles); + VectorCopy(fs->angles, pmove->oldangles); + pmove->friction = fs->friction; + pmove->usehull = fs->usehull; + pmove->oldbuttons = fs->oldbuttons; + pmove->dead = (fcd->health <= 0.0f ) ? true : false; + pmove->spectator = (fs->spectator != 0); + pmove->movetype = fs->movetype; + pmove->gravity = fs->gravity; + pmove->effects = fs->effects; + pmove->iStepLeft = fs->iStepLeft; + pmove->flFallVelocity = fs->flFallVelocity; + Q_strncpy( pmove->physinfo, fcd->physinfo, MAX_INFO_STRING ); + pmove->maxspeed = clgame.movevars.maxspeed; + pmove->clientmaxspeed = fcd->maxspeed; + pmove->cmd = cmd; + pmove->iuser1 = fcd->iuser1; + pmove->iuser2 = fcd->iuser2; + pmove->iuser3 = fcd->iuser3; + pmove->iuser4 = fcd->iuser4; + pmove->fuser1 = fcd->fuser1; + pmove->fuser2 = fcd->fuser2; + pmove->fuser3 = fcd->fuser3; + pmove->fuser4 = fcd->fuser4; + VectorCopy(fcd->vuser1, pmove->vuser1); + VectorCopy(fcd->vuser2, pmove->vuser2); + VectorCopy(fcd->vuser3, pmove->vuser3); + VectorCopy(fcd->vuser4, pmove->vuser4); + + clgame.dllFuncs.pfnPlayerMove( pmove, false ); + + tcd->flags = pmove->flags; + tcd->bInDuck = pmove->bInDuck; + tcd->flTimeStepSound = pmove->flTimeStepSound; + tcd->flDuckTime = (int)pmove->flDuckTime; + tcd->flSwimTime = (int)pmove->flSwimTime; + tcd->waterjumptime = (int)pmove->waterjumptime; + tcd->watertype = pmove->watertype; + tcd->waterlevel = pmove->waterlevel; + tcd->maxspeed = pmove->clientmaxspeed; + tcd->deadflag = pmove->deadflag; + VectorCopy(pmove->velocity, tcd->velocity); + VectorCopy(pmove->view_ofs, tcd->view_ofs); + VectorCopy(pmove->origin, ts->origin); + VectorCopy(pmove->basevelocity, ts->basevelocity); + VectorCopy(pmove->punchangle, tcd->punchangle); + ts->oldbuttons = pmove->oldbuttons; + ts->friction = pmove->friction; + ts->movetype = pmove->movetype; + ts->effects = pmove->effects; + ts->usehull = pmove->usehull; + ts->iStepLeft = pmove->iStepLeft; + ts->flFallVelocity = pmove->flFallVelocity; + tcd->iuser1 = pmove->iuser1; + tcd->iuser2 = pmove->iuser2; + tcd->iuser3 = pmove->iuser3; + tcd->iuser4 = pmove->iuser4; + tcd->fuser1 = pmove->fuser1; + tcd->fuser2 = pmove->fuser2; + tcd->fuser3 = pmove->fuser3; + tcd->fuser4 = pmove->fuser4; + VectorCopy(pmove->vuser1, tcd->vuser1); + VectorCopy(pmove->vuser2, tcd->vuser2); + VectorCopy(pmove->vuser3, tcd->vuser3); + VectorCopy(pmove->vuser4, tcd->vuser4); + + clgame.dllFuncs.pfnPostRunCmd(from, to, &cmd, runfuncs, *pfElapsed, random_seed); + *pfElapsed += cmd.msec / 1000.0; } /* @@ -789,12 +841,12 @@ Sets cl.predicted_origin and cl.predicted_angles */ void CL_PredictMovement( void ) { + double time; int frame = 1; int ack, outgoing_command; int current_command; int current_command_mod; - cl_entity_t *player, *viewent; - clientdata_t *cd; + local_state_t *from, *to; if( cls.state != ca_active ) return; @@ -806,29 +858,30 @@ void CL_PredictMovement( void ) if( cl.refdef.paused || cls.key_dest == key_menu ) return; - player = CL_GetLocalPlayer (); - viewent = CL_GetEntityByIndex( cl.refdef.viewentity ); - cd = &cl.frame.local.client; - // unpredicted pure angled values converted into axis AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up ); + ASSERT( cl.refdef.cmd != NULL ); + if( !CL_IsPredicted( )) { - // run commands even if client predicting is disabled - client expected it - clgame.pmove->runfuncs = true; - CL_PostRunCmd( cl.refdef.cmd, cls.lastoutgoingcommand ); + local_state_t t1, t2; + Q_memset( &t1, 0, sizeof( local_state_t )); + Q_memset( &t2, 0, sizeof( local_state_t )); + + clgame.dllFuncs.pfnPostRunCmd( &t1, &t2, cl.refdef.cmd, false, cl.time, cls.lastoutgoingcommand ); return; } ack = cls.netchan.incoming_acknowledged; outgoing_command = cls.netchan.outgoing_sequence; - ASSERT( cl.refdef.cmd != NULL ); + from = &cl.predict[cl.parsecountmod]; + from->playerstate = cl.frame.playerstate[cl.playernum]; + from->client = cl.frame.local.client; + Q_memcpy( from->weapondata, cl.frame.local.weapondata, sizeof( from->weapondata )); - // setup initial pmove state - CL_SetupPMove( clgame.pmove, cd, &player->curstate, cl.refdef.cmd ); - clgame.pmove->runfuncs = false; + time = cl.frame.time; while( 1 ) { @@ -841,22 +894,23 @@ void CL_PredictMovement( void ) current_command_mod = current_command & CL_UPDATE_MASK; // we've caught up to the current command. - if( current_command > outgoing_command ) + if( current_command >= outgoing_command ) break; - clgame.pmove->cmd = cl.cmds[frame]; + to = &cl.predict[( cl.parsecountmod + frame ) & CL_UPDATE_MASK]; - // motor! - clgame.dllFuncs.pfnPlayerMove( clgame.pmove, false ); // run frames - clgame.pmove->runfuncs = ( current_command > outgoing_command - 1 ) ? true : false; + CL_RunUsercmd( from, to, &cl.cmds[current_command_mod], + cl.runfuncs[current_command_mod], + &time, cls.netchan.incoming_acknowledged + frame ); + cl.runfuncs[current_command_mod] = FALSE; + + from = to; frame++; } - CL_PostRunCmd( cl.refdef.cmd, frame ); - - // copy results out for rendering - VectorCopy( clgame.pmove->view_ofs, cl.predicted_viewofs ); - VectorCopy( clgame.pmove->origin, cl.predicted_origin ); - VectorCopy( clgame.pmove->velocity, cl.predicted_velocity ); + VectorCopy( to->playerstate.origin, cl.predicted_origin ); + VectorCopy( to->client.velocity, cl.predicted_velocity ); + VectorCopy( to->client.view_ofs, cl.predicted_viewofs ); + VectorCopy( to->client.punchangle, cl.predicted_punchangle ); } \ No newline at end of file diff --git a/engine/client/client.h b/engine/client/client.h index ddd54abc..94eb8a4c 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -93,7 +93,7 @@ typedef struct double mtime[2]; // the timestamp of the last two messages - + int last_command_ack; int last_incoming_sequence; qboolean force_send_usercmd; @@ -105,10 +105,11 @@ typedef struct client_data_t data; // some clientdata holds frame_t frame; // received from server - int predictcount; // advances with next clientdata + frame_t frames[MULTIPLAYER_BACKUP]; // alloced on svc_serverdata usercmd_t cmds[MULTIPLAYER_BACKUP]; // each mesage will send several old cmds local_state_t predict[MULTIPLAYER_BACKUP]; // local client state + qboolean runfuncs[MULTIPLAYER_BACKUP]; double time; // this is the time value that the client // is rendering at. always <= cls.realtime @@ -127,6 +128,7 @@ typedef struct vec3_t predicted_origin; // generated by CL_PredictMovement vec3_t predicted_viewofs; vec3_t predicted_velocity; + vec3_t predicted_punchangle; // server state information int playernum; diff --git a/engine/common/build.c b/engine/common/build.c index 49cb0feb..444b0413 100644 --- a/engine/common/build.c +++ b/engine/common/build.c @@ -23,7 +23,7 @@ static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int Q_buildnum( void ) { // do not touch this! Only author of Xash3D can increase buildnumbers! -#if 0 +#if 1 int m = 0, d = 0, y = 0; static int b = 0; diff --git a/engine/common/common.h b/engine/common/common.h index ac17adaf..63366de4 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -878,6 +878,7 @@ void S_Shutdown( void ); void S_Activate( qboolean active, void *hInst ); void S_StopSound( int entnum, int channel, const char *soundname ); int S_GetCurrentStaticSounds( soundlist_t *pout, int size ); +void S_StopBackgroundTrack( void ); void S_StopAllSounds( void ); // gamma routines diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 37d71b3e..89d57f5b 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -2132,6 +2132,7 @@ qboolean SV_LoadGame( const char *pName ) sv.background = false; SCR_BeginLoadingPlaque ( false ); + S_StopBackgroundTrack(); MsgDev( D_INFO, "Loading game from %s...\n", name ); SV_ClearSaveDir();