mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 15:21:44 +00:00
Make the client asynchronous, e.g. decouble net and refresh frames.
This is largely based upon the cl_async 1 mode from KMQuake2, which in turn is based upon r1q2. The origins of this code may be even older... Different to KMQuake2 the asynchonous mode is not optional, the client is always asynchonous. Since we're mainly integrating this rather fundamental change to simplify the complex internal timing between client, server and refresh, there's no point in keeping it optional. The old cl_maxfps cvar controls the network frames. 30 frames should be enough, even Q3A hasn't more. The new gl_maxfps cvar controls the render frames. It's set to 95 fps by default to avoid possible remnant of the famous 125hz bug.
This commit is contained in:
parent
fa4eacc976
commit
4ae8706d22
7 changed files with 307 additions and 127 deletions
|
@ -418,6 +418,7 @@ CL_RequestNextDownload(void)
|
|||
|
||||
MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString(&cls.netchan.message, va("begin %i\n", precache_spawncount));
|
||||
cls.forcePacket = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -500,6 +501,7 @@ CL_CheckOrDownloadFile(char *filename)
|
|||
}
|
||||
|
||||
cls.downloadnumber++;
|
||||
cls.forcePacket = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -606,6 +608,7 @@ CL_ParseDownload(void)
|
|||
|
||||
MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print(&cls.netchan.message, "nextdl");
|
||||
cls.forcePacket = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -427,12 +427,12 @@ CL_AdjustAngles(void)
|
|||
|
||||
if (in_speed.state & 1)
|
||||
{
|
||||
speed = cls.frametime * cl_anglespeedkey->value;
|
||||
speed = cls.nframetime * cl_anglespeedkey->value;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
speed = cls.frametime;
|
||||
speed = cls.nframetime;
|
||||
}
|
||||
|
||||
if (!(in_strafe.state & 1))
|
||||
|
@ -553,7 +553,7 @@ CL_FinishMove(usercmd_t *cmd)
|
|||
}
|
||||
|
||||
/* send milliseconds of time to apply the move */
|
||||
ms = cls.frametime * 1000;
|
||||
ms = cls.nframetime * 1000;
|
||||
|
||||
if (ms > 250)
|
||||
{
|
||||
|
@ -576,36 +576,6 @@ CL_FinishMove(usercmd_t *cmd)
|
|||
cmd->lightlevel = (byte)cl_lightlevel->value;
|
||||
}
|
||||
|
||||
usercmd_t
|
||||
CL_CreateCmd(void)
|
||||
{
|
||||
usercmd_t cmd;
|
||||
|
||||
frame_msec = sys_frame_time - old_sys_frame_time;
|
||||
|
||||
if (frame_msec < 1)
|
||||
{
|
||||
frame_msec = 1;
|
||||
}
|
||||
|
||||
if (frame_msec > 200)
|
||||
{
|
||||
frame_msec = 200;
|
||||
}
|
||||
|
||||
/* get basic movement from keyboard */
|
||||
CL_BaseMove(&cmd);
|
||||
|
||||
/* allow mice or other external controllers to add to the move */
|
||||
IN_Move(&cmd);
|
||||
|
||||
CL_FinishMove(&cmd);
|
||||
|
||||
old_sys_frame_time = sys_frame_time;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void
|
||||
IN_CenterView(void)
|
||||
{
|
||||
|
@ -662,6 +632,123 @@ CL_InitInput(void)
|
|||
cl_nodelta = Cvar_Get("cl_nodelta", "0", 0);
|
||||
}
|
||||
|
||||
void
|
||||
CL_RefreshCmd(void)
|
||||
{
|
||||
int ms;
|
||||
usercmd_t *cmd;
|
||||
|
||||
// CMD to fill
|
||||
cmd = &cl.cmds[cls.netchan.outgoing_sequence & (CMD_BACKUP - 1)];
|
||||
|
||||
// Calculate delta
|
||||
frame_msec = sys_frame_time - old_sys_frame_time;
|
||||
|
||||
// Check bounds
|
||||
if (frame_msec < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (frame_msec > 200)
|
||||
{
|
||||
frame_msec = 200;
|
||||
}
|
||||
|
||||
// Add movement
|
||||
CL_BaseMove(cmd);
|
||||
IN_Move(cmd);
|
||||
|
||||
// Clamp angels for prediction
|
||||
CL_ClampPitch();
|
||||
|
||||
cmd->angles[0] = ANGLE2SHORT(cl.viewangles[0]);
|
||||
cmd->angles[1] = ANGLE2SHORT(cl.viewangles[1]);
|
||||
cmd->angles[2] = ANGLE2SHORT(cl.viewangles[2]);
|
||||
|
||||
// Update time for prediction
|
||||
ms = (int)(cls.nframetime * 1000.0f);
|
||||
|
||||
if (ms > 250)
|
||||
{
|
||||
ms = 100;
|
||||
}
|
||||
|
||||
cmd->msec = ms;
|
||||
|
||||
// Update frame time for the next call
|
||||
old_sys_frame_time = sys_frame_time;
|
||||
|
||||
// Important events are send immediately
|
||||
if (((in_attack.state & 2)) || (in_use.state & 2))
|
||||
{
|
||||
cls.forcePacket = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CL_RefreshMove(void)
|
||||
{
|
||||
usercmd_t *cmd;
|
||||
|
||||
// CMD to fill
|
||||
cmd = &cl.cmds[cls.netchan.outgoing_sequence & (CMD_BACKUP - 1)];
|
||||
|
||||
// Calculate delta
|
||||
frame_msec = sys_frame_time - old_sys_frame_time;
|
||||
|
||||
// Check bounds
|
||||
if (frame_msec < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (frame_msec > 200)
|
||||
{
|
||||
frame_msec = 200;
|
||||
}
|
||||
|
||||
// Add movement
|
||||
CL_BaseMove(cmd);
|
||||
IN_Move(cmd);
|
||||
|
||||
old_sys_frame_time = sys_frame_time;
|
||||
}
|
||||
|
||||
void
|
||||
CL_FinalizeCmd(void)
|
||||
{
|
||||
usercmd_t *cmd;
|
||||
|
||||
// CMD to fill
|
||||
cmd = &cl.cmds[cls.netchan.outgoing_sequence & (CMD_BACKUP - 1)];
|
||||
|
||||
// Mouse button events
|
||||
if (in_attack.state & 3)
|
||||
{
|
||||
cmd->buttons |= BUTTON_ATTACK;
|
||||
}
|
||||
|
||||
in_attack.state &= ~2;
|
||||
|
||||
if (in_use.state & 3)
|
||||
{
|
||||
cmd->buttons |= BUTTON_USE;
|
||||
}
|
||||
|
||||
in_use.state &= ~2;
|
||||
|
||||
// Keyboard events
|
||||
if (anykeydown && cls.key_dest == key_game)
|
||||
{
|
||||
cmd->buttons |= BUTTON_ANY;
|
||||
}
|
||||
|
||||
cmd->impulse = in_impulse;
|
||||
in_impulse = 0;
|
||||
|
||||
// Set light level for muzzle flash
|
||||
cmd->lightlevel = (byte)cl_lightlevel->value;
|
||||
}
|
||||
|
||||
void
|
||||
CL_SendCmd(void)
|
||||
{
|
||||
|
@ -672,14 +759,14 @@ CL_SendCmd(void)
|
|||
usercmd_t nullcmd;
|
||||
int checksumIndex;
|
||||
|
||||
/* build a command even if not connected */
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
/* save this command off for prediction */
|
||||
i = cls.netchan.outgoing_sequence & (CMD_BACKUP - 1);
|
||||
cmd = &cl.cmds[i];
|
||||
cl.cmd_time[i] = cls.realtime; /* for netgraph ping calculation */
|
||||
|
||||
*cmd = CL_CreateCmd();
|
||||
CL_FinalizeCmd();
|
||||
|
||||
cl.cmd = *cmd;
|
||||
|
||||
|
@ -691,10 +778,9 @@ CL_SendCmd(void)
|
|||
if (cls.state == ca_connected)
|
||||
{
|
||||
if (cls.netchan.message.cursize ||
|
||||
(curtime - cls.netchan.last_sent > 100))
|
||||
(curtime - cls.netchan.last_sent > 1000))
|
||||
{
|
||||
byte zero_data = 0;
|
||||
Netchan_Transmit(&cls.netchan, 0, &zero_data);
|
||||
Netchan_Transmit(&cls.netchan, 0, buf.data);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -761,5 +847,9 @@ CL_SendCmd(void)
|
|||
|
||||
/* deliver the message */
|
||||
Netchan_Transmit(&cls.netchan, buf.cursize, buf.data);
|
||||
|
||||
/* Reinit the current cmd buffer */
|
||||
cmd = &cl.cmds[cls.netchan.outgoing_sequence & (CMD_BACKUP - 1)];
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ CL_RunDLights(void)
|
|||
return;
|
||||
}
|
||||
|
||||
dl->radius -= cls.frametime * dl->decay;
|
||||
dl->radius -= cls.rframetime * dl->decay;
|
||||
|
||||
if (dl->radius < 0)
|
||||
{
|
||||
|
|
|
@ -95,6 +95,7 @@ cvar_t *hand;
|
|||
cvar_t *gender;
|
||||
cvar_t *gender_auto;
|
||||
|
||||
cvar_t *gl_maxfps;
|
||||
|
||||
cvar_t *gl_stereo;
|
||||
cvar_t *gl_stereo_separation;
|
||||
|
@ -506,7 +507,7 @@ CL_InitLocal(void)
|
|||
cl_noskins = Cvar_Get("cl_noskins", "0", 0);
|
||||
cl_autoskins = Cvar_Get("cl_autoskins", "0", 0);
|
||||
cl_predict = Cvar_Get("cl_predict", "1", 0);
|
||||
cl_maxfps = Cvar_Get("cl_maxfps", "95", CVAR_ARCHIVE);
|
||||
cl_maxfps = Cvar_Get("cl_maxfps", "30", CVAR_ARCHIVE);
|
||||
cl_drawfps = Cvar_Get("cl_drawfps", "0", CVAR_ARCHIVE);
|
||||
|
||||
cl_upspeed = Cvar_Get("cl_upspeed", "200", 0);
|
||||
|
@ -534,6 +535,8 @@ CL_InitLocal(void)
|
|||
cl_paused = Cvar_Get("paused", "0", 0);
|
||||
cl_timedemo = Cvar_Get("timedemo", "0", 0);
|
||||
|
||||
gl_maxfps = Cvar_Get("gl_maxfps", "95", CVAR_ARCHIVE);
|
||||
|
||||
gl_stereo = Cvar_Get( "gl_stereo", "0", CVAR_ARCHIVE );
|
||||
gl_stereo_separation = Cvar_Get( "gl_stereo_separation", "1", CVAR_ARCHIVE );
|
||||
gl_stereo_convergence = Cvar_Get( "gl_stereo_convergence", "1.4", CVAR_ARCHIVE );
|
||||
|
@ -753,41 +756,41 @@ CL_SendCommand(void)
|
|||
void
|
||||
CL_Frame(int msec)
|
||||
{
|
||||
static int extratime;
|
||||
static int lasttimecalled;
|
||||
|
||||
static int packetdelta = 0;
|
||||
static int renderdelta = 0;
|
||||
static int miscdelta = 0;
|
||||
|
||||
qboolean packetframe = true;
|
||||
qboolean renderframe = true;
|
||||
qboolean miscframe = true;
|
||||
|
||||
if (dedicated->value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
extratime += msec;
|
||||
// Adjust deltas
|
||||
packetdelta += msec;
|
||||
renderdelta += msec;
|
||||
miscdelta += msec;
|
||||
|
||||
if (!cl_timedemo->value)
|
||||
// Calculate simulation time
|
||||
cls.nframetime = packetdelta * 0.001f;
|
||||
cls.rframetime = renderdelta * 0.001f;
|
||||
cls.realtime = curtime;
|
||||
cl.time += msec;
|
||||
|
||||
// Don't extrapolate too far ahead
|
||||
if (cls.nframetime > 0.5f)
|
||||
{
|
||||
if ((cls.state == ca_connected) && (extratime < 100))
|
||||
{
|
||||
return; /* don't flood packets out while connecting */
|
||||
}
|
||||
|
||||
if (extratime < 1000 / cl_maxfps->value)
|
||||
{
|
||||
return; /* framerate is too high */
|
||||
}
|
||||
cls.nframetime = 0.5f;
|
||||
}
|
||||
|
||||
/* decide the simulation time */
|
||||
cls.frametime = extratime / 1000.0;
|
||||
|
||||
cl.time += extratime;
|
||||
|
||||
cls.realtime = curtime;
|
||||
|
||||
extratime = 0;
|
||||
|
||||
if (cls.frametime > (1.0 / 5))
|
||||
if (cls.rframetime > 0.5f)
|
||||
{
|
||||
cls.frametime = (1.0 / 5);
|
||||
cls.rframetime = 0.5f;
|
||||
}
|
||||
|
||||
/* if in the debugger last frame, don't timeout */
|
||||
|
@ -796,77 +799,150 @@ CL_Frame(int msec)
|
|||
cls.netchan.last_received = Sys_Milliseconds();
|
||||
}
|
||||
|
||||
/* fetch results from server */
|
||||
CL_ReadPackets();
|
||||
|
||||
/* send a new command message to the server */
|
||||
CL_SendCommand();
|
||||
|
||||
/* predict all unacknowledged movements */
|
||||
CL_PredictMovement();
|
||||
|
||||
/* allow renderer DLL change */
|
||||
VID_CheckChanges();
|
||||
|
||||
if (!cl.refresh_prepped && (cls.state == ca_active))
|
||||
if (!cl_timedemo->value)
|
||||
{
|
||||
CL_PrepRefresh();
|
||||
// Don't flood while connecting
|
||||
if ((cls.state == ca_connected) && (packetdelta < 100))
|
||||
{
|
||||
packetframe = false;
|
||||
}
|
||||
|
||||
// Network frames
|
||||
if (packetdelta < (1000.0f / cl_maxfps->value))
|
||||
{
|
||||
packetframe = false;
|
||||
}
|
||||
else if (cls.nframetime == cls.rframetime)
|
||||
{
|
||||
packetframe = false;
|
||||
}
|
||||
|
||||
// Render frames
|
||||
if (renderdelta < (1000.0f / gl_maxfps->value))
|
||||
{
|
||||
renderframe = false;
|
||||
}
|
||||
|
||||
// Misc. stuff at 10 FPS
|
||||
if (miscdelta < 100.0f)
|
||||
{
|
||||
miscframe = false;
|
||||
}
|
||||
|
||||
// TODO: Do we need the cl_sleep stuff?
|
||||
}
|
||||
else if (msec < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the screen */
|
||||
if (host_speeds->value)
|
||||
// Update input stuff
|
||||
if (packetframe || renderframe)
|
||||
{
|
||||
time_before_ref = Sys_Milliseconds();
|
||||
CL_ReadPackets();
|
||||
Sys_SendKeyEvents();
|
||||
Cbuf_Execute();
|
||||
CL_FixCvarCheats();
|
||||
|
||||
if (cls.state > ca_connecting)
|
||||
{
|
||||
CL_RefreshCmd();
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_RefreshMove();
|
||||
}
|
||||
}
|
||||
|
||||
SCR_UpdateScreen();
|
||||
|
||||
if (host_speeds->value)
|
||||
if (cls.forcePacket || userinfo_modified)
|
||||
{
|
||||
time_after_ref = Sys_Milliseconds();
|
||||
packetframe = true;
|
||||
cls.forcePacket = false;
|
||||
}
|
||||
|
||||
/* update audio */
|
||||
S_Update(cl.refdef.vieworg, cl.v_forward, cl.v_right, cl.v_up);
|
||||
if (packetframe)
|
||||
{
|
||||
packetdelta = 0;
|
||||
|
||||
CL_SendCmd();
|
||||
CL_CheckForResend();
|
||||
}
|
||||
|
||||
if (renderframe)
|
||||
{
|
||||
renderdelta = 0;
|
||||
|
||||
if (miscframe)
|
||||
{
|
||||
miscdelta = 0;
|
||||
|
||||
VID_CheckChanges();
|
||||
}
|
||||
|
||||
CL_PredictMovement(); // TODO: Make called function async
|
||||
|
||||
if (!cl.refresh_prepped && (cls.state == ca_active))
|
||||
{
|
||||
CL_PrepRefresh();
|
||||
}
|
||||
|
||||
/* update the screen */
|
||||
if (host_speeds->value)
|
||||
{
|
||||
time_before_ref = Sys_Milliseconds();
|
||||
}
|
||||
|
||||
SCR_UpdateScreen();
|
||||
|
||||
if (host_speeds->value)
|
||||
{
|
||||
time_after_ref = Sys_Milliseconds();
|
||||
}
|
||||
|
||||
/* update audio */
|
||||
S_Update(cl.refdef.vieworg, cl.v_forward, cl.v_right, cl.v_up);
|
||||
|
||||
#ifdef CDA
|
||||
CDAudio_Update();
|
||||
if (miscframe)
|
||||
{
|
||||
CDAudio_Update();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* advance local effects for next frame */
|
||||
CL_RunDLights();
|
||||
/* advance local effects for next frame */
|
||||
CL_RunDLights();
|
||||
CL_RunLightStyles();
|
||||
SCR_RunCinematic();
|
||||
SCR_RunConsole();
|
||||
|
||||
CL_RunLightStyles();
|
||||
/* Update framecounter */
|
||||
cls.framecount++;
|
||||
|
||||
SCR_RunCinematic();
|
||||
|
||||
SCR_RunConsole();
|
||||
|
||||
cls.framecount++;
|
||||
|
||||
if (log_stats->value)
|
||||
{
|
||||
if (cls.state == ca_active)
|
||||
if (log_stats->value)
|
||||
{
|
||||
if (!lasttimecalled)
|
||||
if (cls.state == ca_active)
|
||||
{
|
||||
lasttimecalled = Sys_Milliseconds();
|
||||
|
||||
if (log_stats_file)
|
||||
if (!lasttimecalled)
|
||||
{
|
||||
fprintf(log_stats_file, "0\n");
|
||||
}
|
||||
}
|
||||
lasttimecalled = Sys_Milliseconds();
|
||||
|
||||
else
|
||||
{
|
||||
int now = Sys_Milliseconds();
|
||||
|
||||
if (log_stats_file)
|
||||
{
|
||||
fprintf(log_stats_file, "%d\n", now - lasttimecalled);
|
||||
if (log_stats_file)
|
||||
{
|
||||
fprintf(log_stats_file, "0\n");
|
||||
}
|
||||
}
|
||||
|
||||
lasttimecalled = now;
|
||||
else
|
||||
{
|
||||
int now = Sys_Milliseconds();
|
||||
|
||||
if (log_stats_file)
|
||||
{
|
||||
fprintf(log_stats_file, "%d\n", now - lasttimecalled);
|
||||
}
|
||||
|
||||
lasttimecalled = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -233,6 +233,7 @@ CL_PredictMovement(void)
|
|||
int i;
|
||||
int step;
|
||||
int oldz;
|
||||
static int last_step_frame = 0;
|
||||
|
||||
if (cls.state != ca_active)
|
||||
{
|
||||
|
@ -272,20 +273,24 @@ CL_PredictMovement(void)
|
|||
}
|
||||
|
||||
/* copy current state to pmove */
|
||||
memset (&pm, 0, sizeof(pm));
|
||||
pm.trace = CL_PMTrace;
|
||||
pm.pointcontents = CL_PMpointcontents;
|
||||
pm_airaccelerate = strtod(cl.configstrings[CS_AIRACCEL], (char **)NULL);
|
||||
pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
|
||||
pm.s = cl.frame.playerstate.pmove;
|
||||
|
||||
VectorSet(pm.mins, -16, -16, -24);
|
||||
VectorSet(pm.maxs, 16, 16, 32);
|
||||
|
||||
/* run frames */
|
||||
while (++ack < current)
|
||||
while (++ack <= current)
|
||||
{
|
||||
frame = ack & (CMD_BACKUP - 1);
|
||||
cmd = &cl.cmds[frame];
|
||||
|
||||
// Ignore null entries
|
||||
if (!cmd->msec)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pm.cmd = *cmd;
|
||||
Pmove(&pm);
|
||||
|
||||
|
@ -297,10 +302,11 @@ CL_PredictMovement(void)
|
|||
oldz = cl.predicted_origins[oldframe][2];
|
||||
step = pm.s.origin[2] - oldz;
|
||||
|
||||
if ((step > 63) && (step < 160) && (pm.s.pm_flags & PMF_ON_GROUND))
|
||||
if (last_step_frame != current && step > 63 && step < 160 && (pm.s.pm_flags & PMF_ON_GROUND))
|
||||
{
|
||||
cl.predicted_step = step * 0.125f;
|
||||
cl.predicted_step_time = cls.realtime - cls.frametime * 500;
|
||||
cl.predicted_step_time = cls.realtime - cls.nframetime * 500;
|
||||
last_step_frame = current;
|
||||
}
|
||||
|
||||
/* copy results out for rendering */
|
||||
|
|
|
@ -319,7 +319,7 @@ SCR_DrawCenterString(void)
|
|||
void
|
||||
SCR_CheckDrawCenterString(void)
|
||||
{
|
||||
scr_centertime_off -= cls.frametime;
|
||||
scr_centertime_off -= cls.rframetime;
|
||||
|
||||
if (scr_centertime_off <= 0)
|
||||
{
|
||||
|
@ -514,7 +514,7 @@ SCR_RunConsole(void)
|
|||
|
||||
if (scr_conlines < scr_con_current)
|
||||
{
|
||||
scr_con_current -= scr_conspeed->value * cls.frametime;
|
||||
scr_con_current -= scr_conspeed->value * cls.rframetime;
|
||||
|
||||
if (scr_conlines > scr_con_current)
|
||||
{
|
||||
|
@ -523,7 +523,7 @@ SCR_RunConsole(void)
|
|||
}
|
||||
else if (scr_conlines > scr_con_current)
|
||||
{
|
||||
scr_con_current += scr_conspeed->value * cls.frametime;
|
||||
scr_con_current += scr_conspeed->value * cls.rframetime;
|
||||
|
||||
if (scr_conlines < scr_con_current)
|
||||
{
|
||||
|
@ -1541,13 +1541,13 @@ SCR_UpdateScreen(void)
|
|||
if (cl_drawfps->value)
|
||||
{
|
||||
char s[8];
|
||||
sprintf(s, "%3.0ffps", 1 / cls.frametime);
|
||||
sprintf(s, "%3.0ffps", 1 / cls.rframetime);
|
||||
DrawString(viddef.width - 64, 0, s);
|
||||
}
|
||||
|
||||
if (scr_timegraph->value)
|
||||
{
|
||||
SCR_DebugGraph(cls.frametime * 300, 0);
|
||||
SCR_DebugGraph(cls.rframetime * 300, 0);
|
||||
}
|
||||
|
||||
if (scr_debuggraph->value || scr_timegraph->value ||
|
||||
|
|
|
@ -210,7 +210,8 @@ typedef struct
|
|||
|
||||
int framecount;
|
||||
int realtime; /* always increasing, no clamping, etc */
|
||||
float frametime; /* seconds since last frame */
|
||||
float rframetime; /* seconds since last render frame */
|
||||
float nframetime; /* network frame time */
|
||||
|
||||
/* screen rendering information */
|
||||
float disable_screen; /* showing loading plaque between levels */
|
||||
|
@ -231,6 +232,8 @@ typedef struct
|
|||
|
||||
int challenge; /* from the server to use for connecting */
|
||||
|
||||
qboolean forcePacket; /* Forces a package to be send at the next frame. */
|
||||
|
||||
FILE *download; /* file transfer from server */
|
||||
char downloadtempname[MAX_OSPATH];
|
||||
char downloadname[MAX_OSPATH];
|
||||
|
@ -438,7 +441,9 @@ extern kbutton_t in_strafe;
|
|||
extern kbutton_t in_speed;
|
||||
|
||||
void CL_InitInput (void);
|
||||
void CL_RefreshCmd(void);
|
||||
void CL_SendCmd (void);
|
||||
void CL_RefreshMove(void);
|
||||
void CL_SendMove (usercmd_t *cmd);
|
||||
|
||||
void CL_ClearState (void);
|
||||
|
|
Loading…
Reference in a new issue