cvar_t cl_netinputpacketsperserverpacket = {CVAR_SAVE, "cl_netinputpacketsperserverpacket", "1.0", "send this many input packets per server packet received"};
cvar_t cl_netinputpacketspersecond = {CVAR_SAVE, "cl_netinputpacketspersecond","20", "how many input packets to send to server each second (only used on old servers, and note this is multiplied by cl_netinputpacketsperserverpacket)"};
+cvar_t cl_netinputpacketspersecond_qw = {CVAR_SAVE, "cl_netinputpacketspersecond","72", "how many input packets to send to a qw server each second (only used on qw servers)"};
cvar_t cl_netinputpacketlosstolerance = {CVAR_SAVE, "cl_netinputpacketlosstolerance", "1", "how many packets in a row can be lost without movement issues when using cl_movement (technically how many input messages to repeat in each packet that have not yet been acknowledged by the server), only affects DP7 and later servers (Quake uses 0, QuakeWorld uses 2, and just for comparison Quake3 uses 1)"};
cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-player entities in QW network protocol"};
void CL_UpdateMoveVars(void)
{
if (cls.protocol == PROTOCOL_QUAKEWORLD)
- cl.movevars_ticrate = 1.0 / bound(1, cl_netinputpacketspersecond.value, 100);
+ cl.movevars_ticrate = 1.0 / bound(1, cl_netinputpacketspersecond_qw.value, 100);
else if (cl.stats[STAT_MOVEVARS_TICRATE])
{
cl.movevars_ticrate = cl.statsf[STAT_MOVEVARS_TICRATE];
return;
// don't send too often or else network connections can get clogged by a high renderer framerate
- packettime = cl.movevars_ticrate / (double)bound(1, cl_netinputpacketsperserverpacket.value, 10);
+ packettime = cl.movevars_ticrate;
+ if (cls.protocol != PROTOCOL_QUAKEWORLD)
+ packettime /= (double)bound(1, cl_netinputpacketsperserverpacket.value, 10);
// send input every frame in singleplayer
if (cl.islocalgame)
packettime = 0;
// quakeworld servers take only frametimes
// predicted dp7 servers take current interpolation time
// unpredicted servers take an echo of the latest server timestamp
+ cl.cmd.time = cl.time;
+ cl.cmd.sequence = cls.movesequence;
if (cls.protocol == PROTOCOL_QUAKEWORLD)
{
if (realtime < lastsendtime + packettime)
return;
- cl.cmd.time = realtime;
cl.cmd.sequence = cls.netcon->qw.outgoing_sequence;
}
- else if (cl.movement_predicted)
- {
- if (realtime < lastsendtime + packettime)
- return;
- cl.cmd.time = cl.time;
- cl.cmd.sequence = cls.movesequence;
- }
else
{
- // unpredicted movement should be sent immediately whenever a server
+ // movement should be sent immediately whenever a server
// packet is received, to minimize ping times
if (!cl.movement_needupdate && realtime < lastsendtime + packettime)
return;
- if (cl.mtime[0] == cl.movecmd[0].time && cl.mtime[1] != cl.mtime[0])
- return;
- cl.cmd.time = cl.mtime[0];
- cl.cmd.sequence = cls.movesequence;
}
// don't let it fall behind if CL_SendMove hasn't been called recently
Cvar_RegisterVariable(&cl_netinputpacketsperserverpacket);
Cvar_RegisterVariable(&cl_netinputpacketspersecond);
+ Cvar_RegisterVariable(&cl_netinputpacketspersecond_qw);
Cvar_RegisterVariable(&cl_netinputpacketlosstolerance);
Cvar_RegisterVariable(&cl_nodelta);
unsigned char cmdlog[32];
char *cmdlogname[32], *temp;
int cmdindex, cmdcount = 0;
+ qboolean qwplayerupdatereceived;
// LordHavoc: moved demo message writing from before the packet parse to
// after the packet parse so that CL_Stop_f can be called by cl_autodemo
{
CL_NetworkTimeReceived(realtime); // qw has no clock
- // slightly kill qw player entities each frame
- for (i = 1;i < cl.maxclients;i++)
- cl.entities_active[i] = false;
-
// kill all qw nails
cl.qw_num_nails = 0;
cls.servermovesequence = cls.netcon->qw.incoming_sequence;
+ qwplayerupdatereceived = false;
+
while (1)
{
if (msg_badread)
break;
case qw_svc_playerinfo:
+ // slightly kill qw player entities now that we know there is
+ // an update of player entities this frame...
+ if (!qwplayerupdatereceived)
+ {
+ qwplayerupdatereceived = true;
+ for (i = 1;i < cl.maxclients;i++)
+ cl.entities_active[i] = false;
+ }
EntityStateQW_ReadPlayerUpdate();
break;
}
}
- // fully kill the still slightly dead qw player entities each frame,
- // but only if a player update was received
- for (i = 1;i <= cl.maxclients;i++)
- if (cl.entities_active[i])
- break;
- if (i <= cl.maxclients)
+ if (qwplayerupdatereceived)
{
- // kill all non-updated entities this frame
+ // fully kill any player entities that were not updated this frame
for (i = 1;i <= cl.maxclients;i++)
if (!cl.entities_active[i])
cl.entities[i].state_current.active = false;
}
- else
- {
- // no update this frame, restore the cl.entities_active for good measure
- for (i = 1;i <= cl.maxclients;i++)
- cl.entities_active[i] = cl.entities[i].state_current.active;
- }
}
else
{
cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0", "swaps left/right speakers for old ISA soundblaster cards"};
extern cvar_t v_flipped;
cvar_t snd_channellayout = {0, "snd_channellayout", "0", "channel layout. Can be 0 (auto - snd_restart needed), 1 (standard layout), or 2 (ALSA layout)"};
+cvar_t snd_mutewhenidle = {CVAR_SAVE, "snd_mutewhenidle", "1", "whether to disable sound output when game window is inactive"};
// Local cvars
static cvar_t nosound = {0, "nosound", "0", "disables sound"};
Cvar_RegisterVariable(&snd_speed);
Cvar_RegisterVariable(&snd_width);
Cvar_RegisterVariable(&snd_channels);
+ Cvar_RegisterVariable(&snd_mutewhenidle);
// COMMANDLINEOPTION: Sound: -nosound disables sound (including CD audio)
if (COM_CheckParm("-nosound"))
#define SND_CHANNELLAYOUT_ALSA 2
extern cvar_t snd_channellayout;
-
extern int snd_blocked; // counter. When > 0, we stop submitting sound to the audio device
extern mempool_t *snd_mempool;
extern cvar_t volume;
extern cvar_t snd_initialized;
extern cvar_t snd_staticvolume;
+extern cvar_t snd_mutewhenidle;
// ====================================================================
static qboolean sound_active = true;
// enable/disable sound on focus gain/loss
- if (!vid_activewindow && sound_active)
+ if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer))
{
- S_BlockSound ();
- sound_active = false;
+ if (!sound_active)
+ {
+ S_UnblockSound ();
+ sound_active = true;
+ }
}
- else if (vid_activewindow && !sound_active)
+ else
{
- S_UnblockSound ();
- sound_active = true;
+ if (sound_active)
+ {
+ S_BlockSound ();
+ sound_active = false;
+ }
}
HandleEvents();
}
// enable/disable sound on focus gain/loss
- if (!vid_activewindow && sound_active)
+ if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer))
{
- S_BlockSound ();
- sound_active = false;
+ if (!sound_active)
+ {
+ S_UnblockSound ();
+ sound_active = true;
+ }
}
- else if (vid_activewindow && !sound_active)
+ else
{
- S_UnblockSound ();
- sound_active = true;
+ if (sound_active)
+ {
+ S_BlockSound ();
+ sound_active = false;
+ }
}
}
vid_activewindow = fActive;
vid_hidden = minimize;
-// enable/disable sound on focus gain/loss
- if (!vid_activewindow && sound_active)
+ // enable/disable sound on focus gain/loss
+ if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer))
{
- S_BlockSound ();
- sound_active = false;
+ if (!sound_active)
+ {
+ S_UnblockSound ();
+ sound_active = true;
+ }
}
- else if (vid_activewindow && !sound_active)
+ else
{
- S_UnblockSound ();
- sound_active = true;
+ if (sound_active)
+ {
+ S_BlockSound ();
+ sound_active = false;
+ }
}
if (fActive)