- Use select() to sleep when idle as opposed to busy waiting.

- Introduce com_busyWait cvar to go back to old behaviour
This commit is contained in:
Thilo Schulz 2011-02-02 16:46:23 +00:00
parent fa8201c9b6
commit e5dbce839a
7 changed files with 206 additions and 183 deletions

13
README
View file

@ -144,7 +144,8 @@ New cvars
com_standalone - Run in standalone mode com_standalone - Run in standalone mode
com_maxfpsUnfocused - Maximum frames per second when unfocused com_maxfpsUnfocused - Maximum frames per second when unfocused
com_maxfpsMinimized - Maximum frames per second when minimized com_maxfpsMinimized - Maximum frames per second when minimized
com_busyWait - Will use a busy loop to wait for rendering
next frame when set to non-zero value.
in_joystickNo - select which joystick to use in_joystickNo - select which joystick to use
in_keyboardDebug - print keyboard debug info in_keyboardDebug - print keyboard debug info
@ -235,6 +236,16 @@ Using Demo Data Files
data, nor is it something that we like to spend much time maintaining or data, nor is it something that we like to spend much time maintaining or
supporting. supporting.
Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps!
Ioquake3 now uses the select() system call to wait for the rendering of the
next frame when com_maxfps was hit. This will improve your CPU load
considerably in these cases. However, not all systems may support a
granularity for its timing functions that is required to perform this waiting
correctly. For instance, ioquake3 tells select() to wait 2 milliseconds, but
really it can only wait for a multiple of 5ms, i.e. 5, 10, 15, 20... ms.
In this case you can always revert back to the old behaviour by setting the
cvar com_busyWait to 1.
QuakeLive mouse acceleration (patch and this text written by TTimo from id) QuakeLive mouse acceleration (patch and this text written by TTimo from id)
I've been using an experimental mouse acceleration code for a while, and I've been using an experimental mouse acceleration code for a while, and
decided to make it available to everyone. Don't be too worried if you don't decided to make it available to everyone. Don't be too worried if you don't

View file

@ -52,14 +52,3 @@ Sys_SendPacket
*/ */
void Sys_SendPacket( int length, void *data, netadr_t to ) { void Sys_SendPacket( int length, void *data, netadr_t to ) {
} }
/*
==================
Sys_GetPacket
Never called by the game logic, just the system event queing
==================
*/
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message ) {
return false;
}

View file

@ -51,14 +51,3 @@ Sys_SendPacket
*/ */
void Sys_SendPacket( int length, void *data, netadr_t to ) { void Sys_SendPacket( int length, void *data, netadr_t to ) {
} }
/*
==================
Sys_GetPacket
Never called by the game logic, just the system event queing
==================
*/
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message ) {
return false;
}

View file

@ -59,7 +59,6 @@ cvar_t *com_developer;
cvar_t *com_dedicated; cvar_t *com_dedicated;
cvar_t *com_timescale; cvar_t *com_timescale;
cvar_t *com_fixedtime; cvar_t *com_fixedtime;
cvar_t *com_dropsim; // 0.0 to 1.0, simulated packet drops
cvar_t *com_journal; cvar_t *com_journal;
cvar_t *com_maxfps; cvar_t *com_maxfps;
cvar_t *com_altivec; cvar_t *com_altivec;
@ -84,6 +83,7 @@ cvar_t *com_minimized;
cvar_t *com_maxfpsMinimized; cvar_t *com_maxfpsMinimized;
cvar_t *com_abnormalExit; cvar_t *com_abnormalExit;
cvar_t *com_standalone; cvar_t *com_standalone;
cvar_t *com_busyWait;
// com_speeds times // com_speeds times
int time_game; int time_game;
@ -91,7 +91,6 @@ int time_frontend; // renderer frontend time
int time_backend; // renderer backend time int time_backend; // renderer backend time
int com_frameTime; int com_frameTime;
int com_frameMsec;
int com_frameNumber; int com_frameNumber;
qboolean com_errorEntered = qfalse; qboolean com_errorEntered = qfalse;
@ -1945,7 +1944,6 @@ EVENT LOOP
static sysEvent_t eventQueue[ MAX_QUEUED_EVENTS ]; static sysEvent_t eventQueue[ MAX_QUEUED_EVENTS ];
static int eventHead = 0; static int eventHead = 0;
static int eventTail = 0; static int eventTail = 0;
static byte sys_packetReceived[ MAX_MSGLEN ];
/* /*
================ ================
@ -1998,8 +1996,6 @@ sysEvent_t Com_GetSystemEvent( void )
{ {
sysEvent_t ev; sysEvent_t ev;
char *s; char *s;
msg_t netmsg;
netadr_t adr;
// return if we have data // return if we have data
if ( eventHead > eventTail ) if ( eventHead > eventTail )
@ -2021,21 +2017,6 @@ sysEvent_t Com_GetSystemEvent( void )
Com_QueueEvent( 0, SE_CONSOLE, 0, 0, len, b ); Com_QueueEvent( 0, SE_CONSOLE, 0, 0, len, b );
} }
// check for network packets
MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) );
if ( Sys_GetPacket ( &adr, &netmsg ) )
{
netadr_t *buf;
int len;
// copy out to a seperate buffer for qeueing
len = sizeof( netadr_t ) + netmsg.cursize;
buf = Z_Malloc( len );
*buf = adr;
memcpy( buf+1, netmsg.data, netmsg.cursize );
Com_QueueEvent( 0, SE_PACKET, 0, 0, len, buf );
}
// return if we have data // return if we have data
if ( eventHead > eventTail ) if ( eventHead > eventTail )
{ {
@ -2195,7 +2176,6 @@ int Com_EventLoop( void ) {
MSG_Init( &buf, bufData, sizeof( bufData ) ); MSG_Init( &buf, bufData, sizeof( bufData ) );
while ( 1 ) { while ( 1 ) {
NET_FlushPacketQueue();
ev = Com_GetEvent(); ev = Com_GetEvent();
// if no more events are available // if no more events are available
@ -2216,57 +2196,26 @@ int Com_EventLoop( void ) {
} }
switch ( ev.evType ) { switch(ev.evType)
default: {
Com_Error( ERR_FATAL, "Com_EventLoop: bad event type %i", ev.evType ); case SE_KEY:
CL_KeyEvent( ev.evValue, ev.evValue2, ev.evTime );
break; break;
case SE_NONE: case SE_CHAR:
break; CL_CharEvent( ev.evValue );
case SE_KEY:
CL_KeyEvent( ev.evValue, ev.evValue2, ev.evTime );
break; break;
case SE_CHAR: case SE_MOUSE:
CL_CharEvent( ev.evValue ); CL_MouseEvent( ev.evValue, ev.evValue2, ev.evTime );
break; break;
case SE_MOUSE: case SE_JOYSTICK_AXIS:
CL_MouseEvent( ev.evValue, ev.evValue2, ev.evTime ); CL_JoystickEvent( ev.evValue, ev.evValue2, ev.evTime );
break; break;
case SE_JOYSTICK_AXIS: case SE_CONSOLE:
CL_JoystickEvent( ev.evValue, ev.evValue2, ev.evTime ); Cbuf_AddText( (char *)ev.evPtr );
Cbuf_AddText( "\n" );
break; break;
case SE_CONSOLE: default:
Cbuf_AddText( (char *)ev.evPtr ); Com_Error( ERR_FATAL, "Com_EventLoop: bad event type %i", ev.evType );
Cbuf_AddText( "\n" );
break;
case SE_PACKET:
// this cvar allows simulation of connections that
// drop a lot of packets. Note that loopback connections
// don't go through here at all.
if ( com_dropsim->value > 0 ) {
static int seed;
if ( Q_random( &seed ) < com_dropsim->value ) {
break; // drop this packet
}
}
evFrom = *(netadr_t *)ev.evPtr;
buf.cursize = ev.evPtrLength - sizeof( evFrom );
// we must copy the contents of the message out, because
// the event buffers are only large enough to hold the
// exact payload, but channel messages need to be large
// enough to hold fragment reassembly
if ( (unsigned)buf.cursize > buf.maxsize ) {
Com_Printf("Com_EventLoop: oversize packet\n");
continue;
}
Com_Memcpy( buf.data, (byte *)((netadr_t *)ev.evPtr + 1), buf.cursize );
if ( com_sv_running->integer ) {
Com_RunAndTimeServerPacket( &evFrom, &buf );
} else {
CL_PacketEvent( evFrom, &buf );
}
break; break;
} }
@ -2639,7 +2588,6 @@ void Com_Init( char *commandLine ) {
// Clear queues // Clear queues
Com_Memset( &eventQueue[ 0 ], 0, MAX_QUEUED_EVENTS * sizeof( sysEvent_t ) ); Com_Memset( &eventQueue[ 0 ], 0, MAX_QUEUED_EVENTS * sizeof( sysEvent_t ) );
Com_Memset( &sys_packetReceived[ 0 ], 0, MAX_MSGLEN * sizeof( byte ) );
// initialize the weak pseudo-random number generator for use later. // initialize the weak pseudo-random number generator for use later.
Com_InitRand(); Com_InitRand();
@ -2720,7 +2668,6 @@ void Com_Init( char *commandLine ) {
com_timescale = Cvar_Get ("timescale", "1", CVAR_CHEAT | CVAR_SYSTEMINFO ); com_timescale = Cvar_Get ("timescale", "1", CVAR_CHEAT | CVAR_SYSTEMINFO );
com_fixedtime = Cvar_Get ("fixedtime", "0", CVAR_CHEAT); com_fixedtime = Cvar_Get ("fixedtime", "0", CVAR_CHEAT);
com_showtrace = Cvar_Get ("com_showtrace", "0", CVAR_CHEAT); com_showtrace = Cvar_Get ("com_showtrace", "0", CVAR_CHEAT);
com_dropsim = Cvar_Get ("com_dropsim", "0", CVAR_CHEAT);
com_speeds = Cvar_Get ("com_speeds", "0", 0); com_speeds = Cvar_Get ("com_speeds", "0", 0);
com_timedemo = Cvar_Get ("timedemo", "0", CVAR_CHEAT); com_timedemo = Cvar_Get ("timedemo", "0", CVAR_CHEAT);
com_cameraMode = Cvar_Get ("com_cameraMode", "0", CVAR_CHEAT); com_cameraMode = Cvar_Get ("com_cameraMode", "0", CVAR_CHEAT);
@ -2740,6 +2687,7 @@ void Com_Init( char *commandLine ) {
com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE ); com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE );
com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM ); com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM );
com_standalone = Cvar_Get( "com_standalone", "0", CVAR_INIT ); com_standalone = Cvar_Get( "com_standalone", "0", CVAR_INIT );
com_busyWait = Cvar_Get("com_busyWait", "0", CVAR_ARCHIVE);
com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE); com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE);
@ -2947,17 +2895,14 @@ Com_Frame
void Com_Frame( void ) { void Com_Frame( void ) {
int msec, minMsec; int msec, minMsec;
static int lastTime; int timeVal;
int key; static int lastTime = 0;
int timeBeforeFirstEvents; int timeBeforeFirstEvents;
int timeBeforeServer; int timeBeforeServer;
int timeBeforeEvents; int timeBeforeEvents;
int timeBeforeClient; int timeBeforeClient;
int timeAfter; int timeAfter;
if ( setjmp (abortframe) ) { if ( setjmp (abortframe) ) {
@ -2970,10 +2915,6 @@ void Com_Frame( void ) {
timeBeforeClient = 0; timeBeforeClient = 0;
timeAfter = 0; timeAfter = 0;
// old net chan encryption key
key = 0x87243987;
// write config file if anything changed // write config file if anything changed
Com_WriteConfiguration(); Com_WriteConfiguration();
@ -2984,37 +2925,62 @@ void Com_Frame( void ) {
timeBeforeFirstEvents = Sys_Milliseconds (); timeBeforeFirstEvents = Sys_Milliseconds ();
} }
// we may want to spin here if things are going too fast // Figure out how much time we have
if ( !com_dedicated->integer && !com_timedemo->integer ) { if(!com_timedemo->integer)
if( com_minimized->integer && com_maxfpsMinimized->integer > 0 ) { {
minMsec = 1000 / com_maxfpsMinimized->integer; if(com_dedicated->integer)
} else if( com_unfocused->integer && com_maxfpsUnfocused->integer > 0 ) { minMsec = SV_FrameMsec();
minMsec = 1000 / com_maxfpsUnfocused->integer; else
} else if( com_maxfps->integer > 0 ) { {
minMsec = 1000 / com_maxfps->integer; if(com_minimized->integer && com_maxfpsMinimized->integer > 0)
} else { minMsec = 1000 / com_maxfpsMinimized->integer;
minMsec = 1; else if(com_unfocused->integer && com_maxfpsUnfocused->integer > 0)
minMsec = 1000 / com_maxfpsUnfocused->integer;
else if(com_maxfps->integer > 0)
minMsec = 1000 / com_maxfps->integer;
else
minMsec = 1;
timeVal = com_frameTime - lastTime;
if(timeVal > minMsec)
{
// Adjust minMsec if previous frame took too long to render so
// that framerate is stable at the requested value.
timeVal -= minMsec;
if(timeVal > minMsec)
minMsec = 0;
else
minMsec -= timeVal;
}
} }
} else {
minMsec = 1;
} }
else
minMsec = 1;
msec = minMsec; timeVal = 0;
do { do
int timeRemaining = minMsec - msec; {
if(com_busyWait->integer)
NET_Sleep(0);
else
NET_Sleep(timeVal);
// The existing Sys_Sleep implementations aren't really msec = Sys_Milliseconds() - com_frameTime;
// precise enough to be of use beyond 100fps
// FIXME: implement a more precise sleep (RDTSC or something) if(msec >= minMsec)
if( timeRemaining >= 10 ) timeVal = 0;
Sys_Sleep( timeRemaining ); else
timeVal = minMsec - msec;
} while(timeVal > 0);
lastTime = com_frameTime;
com_frameTime = Com_EventLoop();
msec = com_frameTime - lastTime;
com_frameTime = Com_EventLoop();
if ( lastTime > com_frameTime ) {
lastTime = com_frameTime; // possible on first frame
}
msec = com_frameTime - lastTime;
} while ( msec < minMsec );
Cbuf_Execute (); Cbuf_Execute ();
if (com_altivec->modified) if (com_altivec->modified)
@ -3023,11 +2989,8 @@ void Com_Frame( void ) {
com_altivec->modified = qfalse; com_altivec->modified = qfalse;
} }
lastTime = com_frameTime;
// mess with msec if needed // mess with msec if needed
com_frameMsec = msec; msec = Com_ModifyMsec(msec);
msec = Com_ModifyMsec( msec );
// //
// server side // server side
@ -3087,6 +3050,9 @@ void Com_Frame( void ) {
} }
#endif #endif
NET_FlushPacketQueue();
// //
// report timing information // report timing information
// //
@ -3120,9 +3086,6 @@ void Com_Frame( void ) {
c_pointcontents = 0; c_pointcontents = 0;
} }
// old net chan encryption key
key = lastTime * 0x87243987;
com_frameNumber++; com_frameNumber++;
} }

View file

@ -107,6 +107,8 @@ static cvar_t *net_port6;
static cvar_t *net_mcast6addr; static cvar_t *net_mcast6addr;
static cvar_t *net_mcast6iface; static cvar_t *net_mcast6iface;
static cvar_t *net_dropsim;
static struct sockaddr socksRelayAddr; static struct sockaddr socksRelayAddr;
static SOCKET ip_socket = INVALID_SOCKET; static SOCKET ip_socket = INVALID_SOCKET;
@ -201,7 +203,7 @@ char *NET_ErrorString( void ) {
default: return "NO ERROR"; default: return "NO ERROR";
} }
#else #else
return strerror (errno); return strerror(socketError);
#endif #endif
} }
@ -524,16 +526,17 @@ qboolean NET_IsLocalAddress( netadr_t adr ) {
/* /*
================== ==================
Sys_GetPacket NET_GetPacket
Never called by the game logic, just the system event queing Receive one packet
================== ==================
*/ */
#ifdef _DEBUG #ifdef _DEBUG
int recvfromCount; int recvfromCount;
#endif #endif
qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { qboolean NET_GetPacket(netadr_t *net_from, msg_t *net_message, fd_set *fdr)
{
int ret; int ret;
struct sockaddr_storage from; struct sockaddr_storage from;
socklen_t fromlen; socklen_t fromlen;
@ -543,7 +546,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
recvfromCount++; // performance check recvfromCount++; // performance check
#endif #endif
if(ip_socket != INVALID_SOCKET) if(ip_socket != INVALID_SOCKET && FD_ISSET(ip_socket, fdr))
{ {
fromlen = sizeof(from); fromlen = sizeof(from);
ret = recvfrom( ip_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen ); ret = recvfrom( ip_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen );
@ -577,7 +580,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
net_message->readcount = 0; net_message->readcount = 0;
} }
if( ret == net_message->maxsize ) { if( ret >= net_message->maxsize ) {
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
return qfalse; return qfalse;
} }
@ -587,7 +590,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
} }
} }
if(ip6_socket != INVALID_SOCKET) if(ip6_socket != INVALID_SOCKET && FD_ISSET(ip6_socket, fdr))
{ {
fromlen = sizeof(from); fromlen = sizeof(from);
ret = recvfrom(ip6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen); ret = recvfrom(ip6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen);
@ -604,7 +607,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
SockadrToNetadr((struct sockaddr *) &from, net_from); SockadrToNetadr((struct sockaddr *) &from, net_from);
net_message->readcount = 0; net_message->readcount = 0;
if(ret == net_message->maxsize) if(ret >= net_message->maxsize)
{ {
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
return qfalse; return qfalse;
@ -615,7 +618,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
} }
} }
if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket) if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket && FD_ISSET(multicast6_socket, fdr))
{ {
fromlen = sizeof(from); fromlen = sizeof(from);
ret = recvfrom(multicast6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen); ret = recvfrom(multicast6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen);
@ -632,7 +635,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
SockadrToNetadr((struct sockaddr *) &from, net_from); SockadrToNetadr((struct sockaddr *) &from, net_from);
net_message->readcount = 0; net_message->readcount = 0;
if(ret == net_message->maxsize) if(ret >= net_message->maxsize)
{ {
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
return qfalse; return qfalse;
@ -1499,6 +1502,8 @@ static qboolean NET_GetCvars( void ) {
modified += net_socksPassword->modified; modified += net_socksPassword->modified;
net_socksPassword->modified = qfalse; net_socksPassword->modified = qfalse;
net_dropsim = Cvar_Get("net_dropsim", "", CVAR_TEMP);
return modified ? qtrue : qfalse; return modified ? qtrue : qfalse;
} }
@ -1627,6 +1632,42 @@ void NET_Shutdown( void ) {
#endif #endif
} }
/*
====================
NET_Event
Called from NET_Sleep which uses select() to determine which sockets have seen action.
====================
*/
void NET_Event(fd_set *fdr)
{
byte bufData[MAX_MSGLEN + 1];
netadr_t from;
msg_t netmsg;
while(1)
{
MSG_Init(&netmsg, bufData, sizeof(bufData));
if(NET_GetPacket(&from, &netmsg, fdr))
{
if(net_dropsim->value > 0.0f && net_dropsim->value <= 100.0f)
{
// com_dropsim->value percent of incoming packets get dropped.
if(rand() < (int) (((double) RAND_MAX) / 100.0 * (double) net_dropsim->value))
continue; // drop this packet
}
if(com_sv_running->integer)
Com_RunAndTimeServerPacket(&from, &netmsg);
else
CL_PacketEvent(from, &netmsg);
}
else
break;
}
}
/* /*
==================== ====================
@ -1635,31 +1676,23 @@ NET_Sleep
Sleeps msec or until something happens on the network Sleeps msec or until something happens on the network
==================== ====================
*/ */
void NET_Sleep( int msec ) { void NET_Sleep(int msec)
{
struct timeval timeout; struct timeval timeout;
fd_set fdset; fd_set fdr;
int highestfd = -1; int highestfd = -1, retval;
if (!com_dedicated->integer) FD_ZERO(&fdr);
return; // we're not a server, just run full speed
if (ip_socket == INVALID_SOCKET && ip6_socket == INVALID_SOCKET)
return;
if (msec < 0 )
return;
FD_ZERO(&fdset);
if(ip_socket != INVALID_SOCKET) if(ip_socket != INVALID_SOCKET)
{ {
FD_SET(ip_socket, &fdset); FD_SET(ip_socket, &fdr);
highestfd = ip_socket; highestfd = ip_socket;
} }
if(ip6_socket != INVALID_SOCKET) if(ip6_socket != INVALID_SOCKET)
{ {
FD_SET(ip6_socket, &fdset); FD_SET(ip6_socket, &fdr);
if(ip6_socket > highestfd) if(ip6_socket > highestfd)
highestfd = ip6_socket; highestfd = ip6_socket;
@ -1667,9 +1700,32 @@ void NET_Sleep( int msec ) {
timeout.tv_sec = msec/1000; timeout.tv_sec = msec/1000;
timeout.tv_usec = (msec%1000)*1000; timeout.tv_usec = (msec%1000)*1000;
select(highestfd + 1, &fdset, NULL, NULL, &timeout);
}
#ifdef _WIN32
if(highestfd < 0)
{
// windows ain't happy when select is called without valid FDs
if(msec > 0)
msec--;
SleepEx(msec, 0);
return;
}
#define TVW32_BIAS 999
// windows adds a whole millisecond of latency, otherwise granularity seems to be fine.
if(timeout.tv_usec > TVW32_BIAS)
timeout.tv_usec -= TVW32_BIAS;
#endif
retval = select(highestfd + 1, &fdr, NULL, NULL, &timeout);
if(retval < 0)
Com_Printf("Warning: select() syscall failed: %s\n", NET_ErrorString());
else if(retval > 0)
NET_Event(&fdr);
}
/* /*
==================== ====================

View file

@ -768,13 +768,12 @@ typedef enum
typedef enum { typedef enum {
// SE_NONE must be zero // SE_NONE must be zero
SE_NONE = 0, // evTime is still valid SE_NONE = 0, // evTime is still valid
SE_KEY, // evValue is a key code, evValue2 is the down flag SE_KEY, // evValue is a key code, evValue2 is the down flag
SE_CHAR, // evValue is an ascii char SE_CHAR, // evValue is an ascii char
SE_MOUSE, // evValue and evValue2 are reletive signed x / y moves SE_MOUSE, // evValue and evValue2 are reletive signed x / y moves
SE_JOYSTICK_AXIS, // evValue is an axis number and evValue2 is the current state (-127 to 127) SE_JOYSTICK_AXIS, // evValue is an axis number and evValue2 is the current state (-127 to 127)
SE_CONSOLE, // evPtr is a char* SE_CONSOLE // evPtr is a char*
SE_PACKET // evPtr is a netadr_t followed by data bytes to evPtrLength
} sysEventType_t; } sysEventType_t;
typedef struct { typedef struct {
@ -807,6 +806,7 @@ int Com_Filter(char *filter, char *name, int casesensitive);
int Com_FilterPath(char *filter, char *name, int casesensitive); int Com_FilterPath(char *filter, char *name, int casesensitive);
int Com_RealTime(qtime_t *qtime); int Com_RealTime(qtime_t *qtime);
qboolean Com_SafeMode( void ); qboolean Com_SafeMode( void );
void Com_RunAndTimeServerPacket(netadr_t *evFrom, msg_t *buf);
void Com_StartupVariable( const char *match ); void Com_StartupVariable( const char *match );
// checks for and removes command line "+set var arg" constructs // checks for and removes command line "+set var arg" constructs
@ -845,7 +845,6 @@ extern int time_frontend;
extern int time_backend; // renderer backend time extern int time_backend; // renderer backend time
extern int com_frameTime; extern int com_frameTime;
extern int com_frameMsec;
extern qboolean com_errorEntered; extern qboolean com_errorEntered;
@ -997,6 +996,7 @@ void SV_Init( void );
void SV_Shutdown( char *finalmsg ); void SV_Shutdown( char *finalmsg );
void SV_Frame( int msec ); void SV_Frame( int msec );
void SV_PacketEvent( netadr_t from, msg_t *msg ); void SV_PacketEvent( netadr_t from, msg_t *msg );
int SV_FrameMsec(void);
qboolean SV_GameCommand( void ); qboolean SV_GameCommand( void );
@ -1068,7 +1068,6 @@ cpuFeatures_t Sys_GetProcessorFeatures( void );
void Sys_SetErrorText( const char *text ); void Sys_SetErrorText( const char *text );
void Sys_SendPacket( int length, const void *data, netadr_t to ); void Sys_SendPacket( int length, const void *data, netadr_t to );
qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message );
qboolean Sys_StringToAdr( const char *s, netadr_t *a, netadrtype_t family ); qboolean Sys_StringToAdr( const char *s, netadr_t *a, netadrtype_t family );
//Does NOT parse port numbers, only base addresses. //Does NOT parse port numbers, only base addresses.

View file

@ -30,17 +30,17 @@ serverStatic_t svs; // persistant server info
server_t sv; // local server server_t sv; // local server
vm_t *gvm = NULL; // game virtual machine vm_t *gvm = NULL; // game virtual machine
cvar_t *sv_fps; // time rate for running non-clients cvar_t *sv_fps = NULL; // time rate for running non-clients
cvar_t *sv_timeout; // seconds without any message cvar_t *sv_timeout; // seconds without any message
cvar_t *sv_zombietime; // seconds to sink messages after disconnect cvar_t *sv_zombietime; // seconds to sink messages after disconnect
cvar_t *sv_rconPassword; // password for remote server commands cvar_t *sv_rconPassword; // password for remote server commands
cvar_t *sv_privatePassword; // password for the privateClient slots cvar_t *sv_privatePassword; // password for the privateClient slots
cvar_t *sv_allowDownload; cvar_t *sv_allowDownload;
cvar_t *sv_maxclients; cvar_t *sv_maxclients;
cvar_t *sv_privateClients; // number of clients reserved for password cvar_t *sv_privateClients; // number of clients reserved for password
cvar_t *sv_hostname; cvar_t *sv_hostname;
cvar_t *sv_master[MAX_MASTER_SERVERS]; // master server ip address cvar_t *sv_master[MAX_MASTER_SERVERS]; // master server ip address
cvar_t *sv_reconnectlimit; // minimum seconds between connect messages cvar_t *sv_reconnectlimit; // minimum seconds between connect messages
cvar_t *sv_showloss; // report when usercmds are lost cvar_t *sv_showloss; // report when usercmds are lost
cvar_t *sv_padPackets; // add nop bytes to messages cvar_t *sv_padPackets; // add nop bytes to messages
@ -1000,6 +1000,29 @@ static qboolean SV_CheckPaused( void ) {
return qtrue; return qtrue;
} }
/*
==================
SV_FrameMsec
Return time in millseconds until processing of the next server frame.
==================
*/
int SV_FrameMsec()
{
if(sv_fps)
{
int frameMsec;
frameMsec = 1000.0f / sv_fps->value;
if(frameMsec < sv.timeResidual)
return 0;
else
return frameMsec - sv.timeResidual;
}
else
return 1;
}
/* /*
================== ==================
SV_Frame SV_Frame
@ -1052,13 +1075,6 @@ void SV_Frame( int msec ) {
if (!com_dedicated->integer) SV_BotFrame (sv.time + sv.timeResidual); if (!com_dedicated->integer) SV_BotFrame (sv.time + sv.timeResidual);
if ( com_dedicated->integer && sv.timeResidual < frameMsec ) {
// NET_Sleep will give the OS time slices until either get a packet
// or time enough for a server frame has gone by
NET_Sleep(frameMsec - sv.timeResidual);
return;
}
// if time is about to hit the 32nd bit, kick all clients // if time is about to hit the 32nd bit, kick all clients
// and clear sv.time, rather // and clear sv.time, rather
// than checking for negative time wraparound everywhere. // than checking for negative time wraparound everywhere.