09 Jul 2015

This commit is contained in:
g-cont 2015-07-09 00:00:00 +03:00 committed by Alibek Omarov
parent 22463c1fc8
commit 733b2e6b3b
8 changed files with 182 additions and 112 deletions

View File

@ -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;
}
/*

View File

@ -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;
}
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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();