Various fixes and additions

This commit is contained in:
OM 2023-05-28 20:19:35 +02:00
parent 7b79877516
commit c1213e6027
17 changed files with 1470 additions and 887 deletions

View file

@ -1144,9 +1144,9 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
|| key == K_MOUSE5 )
{
if( down ) {
cl.mouseButtons |= ( 1 << ( key + 75 ) );
cl.mouseButtons |= ( 1 << ( key + (256 - K_MOUSE1) ) );
} else {
cl.mouseButtons &= ~( 1 << ( key + 75 ) );
cl.mouseButtons &= ~( 1 << ( key + (256 - K_MOUSE1)) );
}
}

View file

@ -829,7 +829,7 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) {
clc.state = CA_CHALLENGING; // so the connect screen is drawn
clc.connectStartTime = cls.realtime;
clc.connectTime = -RETRANSMIT_TIMEOUT;
NET_StringToAdr(cls.servername, &clc.serverAddress);
NET_StringToAdr(cls.servername, &clc.serverAddress, NA_UNSPEC);
// we don't need a challenge on the localhost
CL_CheckForResend();
@ -996,7 +996,7 @@ void CL_RequestMotd( void ) {
return;
}
Com_Printf( "Resolving %s\n", UPDATE_SERVER_NAME );
if ( !NET_StringToAdr( UPDATE_SERVER_NAME, &cls.updateServer ) ) {
if ( !NET_StringToAdr( UPDATE_SERVER_NAME, &cls.updateServer, NA_IP ) ) {
Com_Printf( "Couldn't resolve address\n" );
return;
}
@ -1067,7 +1067,7 @@ void CL_RequestAuthorization( void ) {
if ( !cls.authorizeServer.port ) {
Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &cls.authorizeServer ) ) {
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &cls.authorizeServer, NA_IP ) ) {
Com_Printf( "Couldn't resolve address\n" );
return;
}
@ -1228,7 +1228,7 @@ void CL_Connect( const char *server ) {
Q_strncpyz( cls.servername, server, sizeof( cls.servername ) );
if( !NET_StringToAdr( cls.servername, &clc.serverAddress ) ) {
if( !NET_StringToAdr( cls.servername, &clc.serverAddress, NA_IP ) ) {
Com_Printf( "Bad server address\n" );
clc.state = CA_DISCONNECTED;
return;
@ -1383,7 +1383,7 @@ void CL_Rcon_f( void ) {
return;
}
NET_StringToAdr (rconAddress->string, &to);
NET_StringToAdr (rconAddress->string, &to, NA_IP);
if (to.port == 0) {
to.port = BigShort (PORT_SERVER);
}
@ -3516,7 +3516,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma
return qfalse;
}
// get the address
if ( !NET_StringToAdr( serverAddress, &to ) ) {
if ( !NET_StringToAdr( serverAddress, &to, NA_IP ) ) {
return qfalse;
}
serverStatus = CL_GetServerStatus( to );
@ -3840,7 +3840,7 @@ void CL_GlobalServers_f( void ) {
// reset the list, waiting for response
// -1 is used to distinguish a "no response"
NET_StringToAdr( cl_master->string, &to );
NET_StringToAdr( cl_master->string, &to, NA_IP );
if( cls.masterNum == 1 ) {
cls.nummplayerservers = -1;
@ -4053,7 +4053,7 @@ void CL_Ping_f( void ) {
server = Cmd_Argv(1);
if ( !NET_StringToAdr( server, &to ) ) {
if ( !NET_StringToAdr( server, &to, NA_IP ) ) {
return;
}
@ -4298,7 +4298,7 @@ void CL_ServerStatus_f(void) {
server = Cmd_Argv(1);
}
if ( !NET_StringToAdr( server, &to ) ) {
if ( !NET_StringToAdr( server, &to, NA_IP ) ) {
return;
}

View file

@ -381,7 +381,7 @@ static int LAN_AddServer(int source, const char *name, const char *address) {
break;
}
if (servers && *count < max) {
NET_StringToAdr( address, &adr );
NET_StringToAdr( address, &adr, NA_IP );
for ( i = 0; i < *count; i++ ) {
if (NET_CompareAdr(servers[i].adr, adr)) {
break;
@ -428,7 +428,7 @@ static void LAN_RemoveServer(int source, const char *addr) {
}
if (servers) {
netadr_t comp;
NET_StringToAdr( addr, &comp );
NET_StringToAdr( addr, &comp, NA_IP );
for (i = 0; i < *count; i++) {
if (NET_CompareAdr( comp, servers[i].adr)) {
int j = i;
@ -3153,7 +3153,7 @@ void CL_PingServers_f( void ) {
{
Com_Printf( "pinging %s...\n", adrstring );
if( NET_StringToAdr( adrstring, &adr ) )
if( NET_StringToAdr( adrstring, &adr, NA_IP ) )
{
if( !adr.port ) {
adr.port = BigShort( 12203 );

View file

@ -85,6 +85,7 @@ cvar_t *com_fixedtime;
cvar_t *com_dropsim; // 0.0 to 1.0, simulated packet drops
cvar_t *com_journal;
cvar_t *com_maxfps;
cvar_t *com_altivec;
cvar_t *com_timedemo;
cvar_t *com_sv_running;
cvar_t *com_cl_running;
@ -1267,6 +1268,23 @@ char cl_cdkey[34] = " ";
char cl_cdkey[34] = "123456789";
#endif
static void Com_DetectAltivec(void)
{
// Only detect if user hasn't forcibly disabled it.
if (com_altivec->integer) {
static qboolean altivec = qfalse;
static qboolean detected = qfalse;
if (!detected) {
altivec = ( Sys_GetProcessorFeatures( ) & CF_ALTIVEC );
detected = qtrue;
}
if (!altivec) {
Cvar_Set( "com_altivec", "0" ); // we don't have it! Disable support!
}
}
}
/*
=================
Com_Init
@ -1398,6 +1416,7 @@ void Com_Init( char *commandLine ) {
low_anim_memory = Cvar_Get( "low_anim_memory", "0", 0 );
showLoad = Cvar_Get( "showLoad", "0", 0 );
convertAnims = Cvar_Get( "convertAnim", "0", 0 );
com_altivec = Cvar_Get ("com_altivec", "1", CVAR_ARCHIVE);
com_maxfps = Cvar_Get( "com_maxfps", "85", CVAR_ARCHIVE );
deathmatch = Cvar_Get( "deathmatch", "0", 0 );
paused = Cvar_Get( "paused", "0", 64 );
@ -1412,11 +1431,19 @@ void Com_Init( char *commandLine ) {
com_speeds = Cvar_Get( "com_speeds", "0", 0 );
com_timedemo = Cvar_Get( "timedemo", "0", CVAR_CHEAT );
com_dedicated = Cvar_Get( "dedicated", "0", CVAR_LATCH );
cl_packetdelay = Cvar_Get( "cl_packetdelay", "0", 0 );
sv_packetdelay = Cvar_Get( "sv_packetdelay", "0", 0 );
com_sv_running = Cvar_Get( "sv_running", "0", CVAR_ROM );
com_cl_running = Cvar_Get( "cl_running", "0", CVAR_ROM );
com_buildScript = Cvar_Get( "com_buildScript", "0", 0 );
cl_packetdelay = Cvar_Get( "cl_packetdelay", "0", 0 );
sv_packetdelay = Cvar_Get( "sv_packetdelay", "0", 0 );
com_ansiColor = Cvar_Get( "com_ansiColor", "0", CVAR_ARCHIVE );
com_unfocused = Cvar_Get( "com_unfocused", "0", CVAR_ROM );
com_maxfpsUnfocused = Cvar_Get( "com_maxfpsUnfocused", "0", CVAR_ARCHIVE );
com_minimized = Cvar_Get( "com_minimized", "0", CVAR_ROM );
com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE );
com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM );
com_busyWait = Cvar_Get("com_busyWait", "0", CVAR_ARCHIVE);
if( com_dedicated->integer )
{
@ -1605,6 +1632,26 @@ int Com_ModifyMsec( int msec ) {
return msec;
}
/*
=================
Com_TimeVal
=================
*/
int Com_TimeVal(int minMsec)
{
int timeVal;
timeVal = Sys_Milliseconds() - com_frameTime;
if(timeVal >= minMsec)
timeVal = 0;
else
timeVal = minMsec - timeVal;
return timeVal;
}
/*
=================
Com_Frame
@ -1613,7 +1660,8 @@ Com_Frame
void Com_Frame( void ) {
int msec, minMsec;
static int lastTime;
int timeVal, timeValSV;
static int lastTime = 0, bias = 0;
int key;
int timeBeforeFirstEvents;
@ -1666,43 +1714,80 @@ void Com_Frame( void ) {
timeBeforeFirstEvents = Sys_Milliseconds ();
}
// we may want to spin here if things are going too fast
if ( !com_dedicated->integer && com_maxfps->integer > 0 && !com_timedemo->integer ) {
minMsec = 1000 / com_maxfps->integer;
} else {
minMsec = 1;
}
do {
com_frameTime = Com_EventLoop();
if ( lastTime > com_frameTime ) {
lastTime = com_frameTime; // possible on first frame
}
msec = com_frameTime - lastTime;
} while ( msec < minMsec );
// Figure out how much time we have
if (!com_timedemo->integer)
{
if (com_dedicated->integer)
minMsec = SV_FrameMsec();
else
{
if (com_minimized->integer && com_maxfpsMinimized->integer > 0)
minMsec = 1000 / com_maxfpsMinimized->integer;
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;
bias += timeVal - minMsec;
if (bias > minMsec)
bias = minMsec;
// Adjust minMsec if previous frame took too long to render so
// that framerate is stable at the requested value.
minMsec -= bias;
}
}
else
minMsec = 1;
do
{
if (com_sv_running->integer)
{
timeValSV = SV_SendQueuedPackets();
timeVal = Com_TimeVal(minMsec);
if (timeValSV < timeVal)
timeVal = timeValSV;
}
else
timeVal = Com_TimeVal(minMsec);
if (com_busyWait->integer || timeVal < 1)
NET_Sleep(0);
else
NET_Sleep(timeVal - 1);
} while (Com_TimeVal(minMsec));
IN_Frame();
#ifndef DEDICATED
if( com_dedicated->integer || CL_FinishedIntro() )
{
Cbuf_Execute( 0 );
}
#else
Cbuf_Execute(0);
#endif
lastTime = com_frameTime;
com_frameTime = Com_EventLoop();
lastTime = com_frameTime;
msec = com_frameTime - lastTime;
// mess with msec if needed
com_frameMsec = msec;
msec = Com_ModifyMsec( msec );
Cbuf_Execute(0);
//
// server side
//
if ( com_speeds->integer ) {
timeBeforeServer = Sys_Milliseconds ();
}
if (com_altivec->modified)
{
Com_DetectAltivec();
com_altivec->modified = qfalse;
}
// mess with msec if needed
msec = Com_ModifyMsec(msec);
//
// server side
//
if (com_speeds->integer) {
timeBeforeServer = Sys_Milliseconds();
}
SV_Frame( msec );
@ -1721,36 +1806,43 @@ void Com_Frame( void ) {
}
#ifndef DEDICATED
if (!com_dedicated->integer) {
//
// client system
//
//
// run event loop a second time to get server to client packets
// without a frame of latency
//
if (com_speeds->integer) {
timeBeforeEvents = Sys_Milliseconds();
}
Com_EventLoop();
Cbuf_Execute(msec);
//
// client system
//
//
// run event loop a second time to get server to client packets
// without a frame of latency
//
if ( com_speeds->integer ) {
timeBeforeEvents = Sys_Milliseconds ();
}
Com_EventLoop();
Cbuf_Execute(msec);
//
// client side
//
if (com_speeds->integer) {
timeBeforeClient = Sys_Milliseconds();
}
//
// client side
//
if ( com_speeds->integer ) {
timeBeforeClient = Sys_Milliseconds ();
}
CL_Frame(msec);
CL_Frame( msec );
if (com_speeds->integer) {
timeAfter = Sys_Milliseconds();
}
if ( com_speeds->integer ) {
timeAfter = Sys_Milliseconds ();
}
#else
if ( com_speeds->integer ) {
timeAfter = Sys_Milliseconds ();
timeBeforeEvents = timeAfter;
timeBeforeClient = timeAfter;
}
#endif
NET_FlushPacketQueue();
//
// report timing information
//

View file

@ -457,78 +457,6 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
return qtrue;
}
//==============================================================================
/*
===================
NET_CompareBaseAdr
Compares without the port
===================
*/
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
{
if (a.type != b.type)
return qfalse;
if (a.type == NA_LOOPBACK)
return qtrue;
if (a.type == NA_IP)
{
if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
return qtrue;
return qfalse;
}
Com_Printf ("NET_CompareBaseAdr: bad address type\n");
return qfalse;
}
const char *NET_AdrToString (netadr_t a)
{
static char s[64];
if (a.type == NA_LOOPBACK) {
Com_sprintf (s, sizeof(s), "loopback");
} else if (a.type == NA_BOT) {
Com_sprintf (s, sizeof(s), "bot");
} else if (a.type == NA_IP) {
Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%hu",
a.ip[0], a.ip[1], a.ip[2], a.ip[3], BigShort(a.port));
}
return s;
}
qboolean NET_CompareAdr (netadr_t a, netadr_t b)
{
if (a.type != b.type)
return qfalse;
if (a.type == NA_LOOPBACK)
return qtrue;
if (a.type == NA_IP)
{
if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
return qtrue;
return qfalse;
}
Com_Printf ("NET_CompareAdr: bad address type\n");
return qfalse;
}
qboolean NET_IsLocalAddress( netadr_t adr ) {
return adr.type == NA_LOOPBACK;
}
/*
=============================================================================

File diff suppressed because it is too large Load diff

View file

@ -1400,6 +1400,18 @@ char *Q_CleanStr( char *string ) {
return string;
}
int Q_CountChar(const char* string, char tocount)
{
int count;
for (count = 0; *string; string++)
{
if (*string == tocount)
count++;
}
return count;
}
size_t QDECL Com_sprintf( char *dest, size_t size, const char *fmt, ...) {
size_t len;

View file

@ -104,7 +104,7 @@ extern "C" {
#define PRODUCT_VERSION_FULL PRODUCT_NAME_FULL
#define Q3_VERSION PRODUCT_VERSION_FULL
#define CLIENT_WINDOW_TITLE PRODUCT_NAME
#define CLIENT_WINDOW_TITLE PRODUCT_NAME_FULL
#define CLIENT_WINDOW_MIN_TITLE PRODUCT_NAME
#define MAX_TEAMNAME 32
@ -1192,6 +1192,8 @@ void Q_strcat( char *dest, int size, const char *src );
int Q_PrintStrlen( const char *string );
// removes color sequences from string
char *Q_CleanStr( char *string );
// Count the number of char tocount encountered in string
int Q_CountChar(const char *string, char tocount);
//=============================================

View file

@ -180,6 +180,13 @@ NET
==============================================================
*/
#define NET_ENABLEV4 0x01
#define NET_ENABLEV6 0x02
// if this flag is set, always attempt ipv6 connections instead of ipv4 if a v6 address is found.
#define NET_PRIOV6 0x04
// disables ipv6 multicast support if set.
#define NET_DISABLEMCAST 0x08
#define PACKET_BACKUP 32 // number of old messages that must be kept on client and
// server for delta comrpession and ping estimation
#define PACKET_MASK (PACKET_BACKUP-1)
@ -197,7 +204,10 @@ typedef enum {
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX
NA_BROADCAST_IPX,
NA_IP6,
NA_MULTICAST6,
NA_UNSPEC
} netadrtype_t;
typedef enum {
@ -206,20 +216,18 @@ typedef enum {
NS_SERVER
} netsrc_t;
#define NET_ADDRSTRMAXLEN 48 // maximum length of an IPv6 address string including trailing '\0'
typedef struct {
netadrtype_t type;
netadrtype_t type;
byte ip[4];
byte ipx[ 10 ];
byte ip[4];
byte ip6[16];
byte ipx[10];
unsigned short port;
unsigned short port;
unsigned long scope_id; // Needed for IPv6 link-local addresses
} netadr_t;
// wombat: gamespy tcp code
qboolean NETGS_CreateMasterSocket( void );
qboolean NETGS_SendMasterRequest( void );
int NETGS_ReceiveMasterResponse( char *buffer, int size );
void NET_Init( void );
void NET_Shutdown( void );
void NET_Restart_f( void );
@ -230,11 +238,15 @@ void QDECL NET_OutOfBandPrint( netsrc_t net_socket, netadr_t adr, const char *f
void QDECL NET_OutOfBandData( netsrc_t sock, netadr_t adr, byte *format, int len );
qboolean NET_CompareAdr (netadr_t a, netadr_t b);
qboolean NET_CompareBaseAdrMask(netadr_t a, netadr_t b, int netmask);
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b);
qboolean NET_IsLocalAddress (netadr_t adr);
const char *NET_AdrToString (netadr_t a);
qboolean NET_StringToAdr ( const char *s, netadr_t *a);
const char *NET_AdrToStringwPort (netadr_t a);
int NET_StringToAdr ( const char *s, netadr_t *a, netadrtype_t family);
qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, msg_t *net_message);
void NET_JoinMulticast6(void);
void NET_LeaveMulticast6(void);
void NET_Sleep(int msec);
@ -271,7 +283,11 @@ typedef struct {
qboolean unsentFragments;
size_t unsentFragmentStart;
size_t unsentLength;
byte unsentBuffer[MAX_MSGLEN];
byte unsentBuffer[MAX_MSGLEN];
int challenge;
int lastSentTime;
int lastSentSize;
} netchan_t;
void Netchan_Init( int qport );
@ -1135,7 +1151,9 @@ void SV_Shutdown( const char *finalmsg );
void SV_SetFrameNumber(int frameNumber);
void SV_Frame( int msec );
void SV_PacketEvent( netadr_t from, msg_t *msg );
qboolean SV_GameCommand( void );
int SV_FrameMsec(void);
qboolean SV_GameCommand(void);
int SV_SendQueuedPackets(void);
//
// input interface

View file

@ -1190,7 +1190,7 @@ void IN_Frame( void )
IN_JoyMove( );
// If not DISCONNECTED (main menu) or ACTIVE (in game), we're loading
loading = ( clc.state != CA_DISCONNECTED && clc.state != CA_ACTIVE );
loading = (clc.state != CA_DISCONNECTED && clc.state != CA_ACTIVE && clc.state != CA_CONNECTING );
// update isFullscreen since it might of changed since the last vid_restart
cls.glconfig.isFullscreen = Cvar_VariableIntegerValue( "r_fullscreen" ) != 0;

View file

@ -304,7 +304,9 @@ extern cvar_t *sv_padPackets;
extern cvar_t *sv_killserver;
extern cvar_t *sv_mapChecksum;
extern cvar_t *sv_serverid;
extern cvar_t *sv_minRate;
extern cvar_t *sv_maxRate;
extern cvar_t *sv_dlRate;
extern cvar_t *sv_minPing;
extern cvar_t *sv_maxPing;
extern cvar_t *sv_pure;
@ -436,7 +438,7 @@ void SV_DropClient( client_t *drop, const char *reason );
void SV_ExecuteClientCommand( client_t *cl, const char *s, qboolean clientOK );
void SV_ClientThink( client_t *cl, usercmd_t *cmd );
void SV_WriteDownloadToClient( client_t *cl , msg_t *msg );
int SV_WriteDownloadToClient( client_t *cl , msg_t *msg );
int SV_SendDownloadMessages(void);
int SV_SendQueuedMessages(void);
@ -538,7 +540,7 @@ void SV_ClipToEntity( trace_t *trace, const vec3_t start, const vec3_t mins, con
// sv_net_chan.c
//
void SV_Netchan_Transmit( client_t *client, msg_t *msg);
void SV_Netchan_TransmitNextFragment( client_t *client );
int SV_Netchan_TransmitNextFragment( client_t *client );
qboolean SV_Netchan_Process( client_t *client, msg_t *msg );
//

View file

@ -397,7 +397,7 @@ static void SV_Ban_f( void ) {
// look up the authorize server's IP
if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) {
Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress ) ) {
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP ) ) {
Com_Printf( "Couldn't resolve address\n" );
return;
}
@ -451,7 +451,7 @@ static void SV_BanNum_f( void ) {
// look up the authorize server's IP
if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) {
Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress ) ) {
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP ) ) {
Com_Printf( "Couldn't resolve address\n" );
return;
}

View file

@ -94,7 +94,7 @@ void SV_GetChallenge( netadr_t from ) {
// look up the authorize server's IP
if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) {
Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress ) ) {
if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP ) ) {
Com_Printf( "Couldn't resolve address\n" );
return;
}
@ -781,7 +781,7 @@ Check to see if the client wants a file, open it if needed and start pumping the
Fill up msg with data
==================
*/
void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
int SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
{
int curindex;
int rate;
@ -792,7 +792,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
int numRefPaks;
if (!*cl->downloadName)
return; // Nothing being downloaded
return 0; // Nothing being downloaded
if (!cl->download) {
// Chop off filename extension.
@ -877,7 +877,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
MSG_WriteString( msg, errorMessage );
*cl->downloadName = 0;
return;
return 1;
}
Com_Printf( "clientDownload: %d : beginning \"%s\"\n", (int) (cl - svs.clients), cl->downloadName );
@ -953,7 +953,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
// automatically start retransmitting
if (cl->downloadClientBlock == cl->downloadCurrentBlock)
return; // Nothing to transmit
return 0; // Nothing to transmit
if (cl->downloadXmitBlock == cl->downloadCurrentBlock) {
// We have transmitted the complete window, should we start resending?
@ -963,7 +963,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
if (svs.time - cl->downloadSendTime > 1000)
cl->downloadXmitBlock = cl->downloadClientBlock;
else
return;
return 0;
}
// Send current block
@ -991,6 +991,80 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
cl->downloadSendTime = svs.time;
}
return 1;
}
/*
==================
SV_SendQueuedMessages
Send one round of fragments, or queued messages to all clients that have data pending.
Return the shortest time interval for sending next packet to client
==================
*/
int SV_SendQueuedMessages(void)
{
int i, retval = -1, nextFragT;
client_t *cl;
for(i=0; i < sv_maxclients->integer; i++)
{
cl = &svs.clients[i];
if(cl->state)
{
nextFragT = SV_RateMsec(cl);
if(!nextFragT)
nextFragT = SV_Netchan_TransmitNextFragment(cl);
if(nextFragT >= 0 && (retval == -1 || retval > nextFragT))
retval = nextFragT;
}
}
return retval;
}
/*
==================
SV_SendDownloadMessages
Send one round of download messages to all clients
==================
*/
int SV_SendDownloadMessages(void)
{
int i, numDLs = 0, retval;
client_t *cl;
msg_t msg;
byte msgBuffer[MAX_MSGLEN];
for(i=0; i < sv_maxclients->integer; i++)
{
cl = &svs.clients[i];
if(cl->state && *cl->downloadName)
{
MSG_Init(&msg, msgBuffer, sizeof(msgBuffer));
MSG_WriteLong(&msg, cl->lastClientCommand);
retval = SV_WriteDownloadToClient(cl, &msg);
if(retval)
{
MSG_WriteByte(&msg, svc_EOF);
SV_Netchan_Transmit(cl, &msg);
numDLs += retval;
}
}
}
return numDLs;
}
/*

View file

@ -979,7 +979,9 @@ void SV_Init( void ) {
sv_privateClients = Cvar_Get( "sv_privateClients", "0", CVAR_SERVERINFO );
sv_hostname = Cvar_Get( "sv_hostname", "Nameless OpenMoHAA Battle", CVAR_SERVERINFO | CVAR_ARCHIVE );
sv_maxclients = Cvar_Get( "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH );
sv_minRate = Cvar_Get ("sv_minRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_maxRate = Cvar_Get( "sv_maxRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_dlRate = Cvar_Get("sv_dlRate", "100", CVAR_ARCHIVE | CVAR_SERVERINFO);
sv_minPing = Cvar_Get( "sv_minPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_maxPing = Cvar_Get( "sv_maxPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_floodProtect = Cvar_Get( "sv_floodProtect", "1", CVAR_ARCHIVE | CVAR_SERVERINFO );

View file

@ -45,7 +45,9 @@ cvar_t *sv_padPackets; // add nop bytes to messages
cvar_t *sv_killserver; // menu system can set to 1 to shut server down
cvar_t *sv_mapChecksum;
cvar_t *sv_serverid;
cvar_t *sv_minRate;
cvar_t *sv_maxRate;
cvar_t *sv_dlRate;
cvar_t *sv_minPing;
cvar_t *sv_maxPing;
cvar_t *sv_pure;
@ -735,6 +737,29 @@ void SV_SetFrameNumber(int frameNumber) {
}
}
/*
==================
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
@ -959,3 +984,132 @@ void SV_SoundCallback( int entnum, int channel_number, const char *name )
//============================================================================
/*
====================
SV_RateMsec
Return the number of msec until another message can be sent to
a client based on its rate settings
====================
*/
#define UDPIP_HEADER_SIZE 28
#define UDPIP6_HEADER_SIZE 48
int SV_RateMsec(client_t* client)
{
int rate, rateMsec;
int messageSize;
messageSize = client->netchan.lastSentSize;
rate = client->rate;
if (sv_maxRate->integer)
{
if (sv_maxRate->integer < 1000)
Cvar_Set("sv_MaxRate", "1000");
if (sv_maxRate->integer < rate)
rate = sv_maxRate->integer;
}
if (sv_minRate->integer)
{
if (sv_minRate->integer < 1000)
Cvar_Set("sv_minRate", "1000");
if (sv_minRate->integer > rate)
rate = sv_minRate->integer;
}
if (client->netchan.remoteAddress.type == NA_IP6)
messageSize += UDPIP6_HEADER_SIZE;
else
messageSize += UDPIP_HEADER_SIZE;
rateMsec = messageSize * 1000 / ((int)(rate * com_timescale->value));
rate = Sys_Milliseconds() - client->netchan.lastSentTime;
if (rate > rateMsec)
return 0;
else
return rateMsec - rate;
}
/*
====================
SV_SendQueuedPackets
Send download messages and queued packets in the time that we're idle, i.e.
not computing a server frame or sending client snapshots.
Return the time in msec until we expect to be called next
====================
*/
int SV_SendQueuedPackets()
{
int numBlocks;
int dlStart, deltaT, delayT;
static int dlNextRound = 0;
int timeVal = INT_MAX;
// Send out fragmented packets now that we're idle
delayT = SV_SendQueuedMessages();
if (delayT >= 0)
timeVal = delayT;
if (sv_dlRate->integer)
{
// Rate limiting. This is very imprecise for high
// download rates due to millisecond timedelta resolution
dlStart = Sys_Milliseconds();
deltaT = dlNextRound - dlStart;
if (deltaT > 0)
{
if (deltaT < timeVal)
timeVal = deltaT + 1;
}
else
{
numBlocks = SV_SendDownloadMessages();
if (numBlocks)
{
// There are active downloads
deltaT = Sys_Milliseconds() - dlStart;
delayT = 1000 * numBlocks * MAX_DOWNLOAD_BLKSIZE;
delayT /= sv_dlRate->integer * 1024;
if (delayT <= deltaT + 1)
{
// Sending the last round of download messages
// took too long for given rate, don't wait for
// next round, but always enforce a 1ms delay
// between DL message rounds so we don't hog
// all of the bandwidth. This will result in an
// effective maximum rate of 1MB/s per user, but the
// low download window size limits this anyways.
if (timeVal > 2)
timeVal = 2;
dlNextRound = dlStart + deltaT + 1;
}
else
{
dlNextRound = dlStart + delayT;
delayT -= deltaT;
if (delayT < timeVal)
timeVal = delayT;
}
}
}
}
else
{
if (SV_SendDownloadMessages())
timeVal = 0;
}
return timeVal;
}

View file

@ -131,7 +131,7 @@ static void SV_Netchan_Decode( client_t *client, msg_t *msg ) {
SV_Netchan_TransmitNextFragment
=================
*/
void SV_Netchan_TransmitNextFragment( client_t *client ) {
int SV_Netchan_TransmitNextFragment( client_t *client ) {
Netchan_TransmitNextFragment( &client->netchan );
if (!client->netchan.unsentFragments)
{
@ -141,11 +141,11 @@ void SV_Netchan_TransmitNextFragment( client_t *client ) {
}
// the last fragment was transmitted, check wether we have queued messages
if (client->netchan_start_queue) {
netchan_buffer_t *netbuf;
netchan_buffer_t* netbuf;
Com_DPrintf("#462 Netchan_TransmitNextFragment: popping a queued message for transmit\n");
netbuf = client->netchan_start_queue;
SV_Netchan_Encode( client, &netbuf->msg );
Netchan_Transmit( &client->netchan, netbuf->msg.cursize, netbuf->msg.data );
SV_Netchan_Encode(client, &netbuf->msg);
Netchan_Transmit(&client->netchan, netbuf->msg.cursize, netbuf->msg.data);
// pop from queue
client->netchan_start_queue = netbuf->next;
if (!client->netchan_start_queue) {
@ -155,8 +155,15 @@ void SV_Netchan_TransmitNextFragment( client_t *client ) {
else
Com_DPrintf("#462 Netchan_TransmitNextFragment: remaining queued message\n");
Z_Free(netbuf);
}
}
return SV_RateMsec(client);
}
}
else
{
return SV_RateMsec(client);
}
return -1;
}

View file

@ -311,7 +311,7 @@ void* Sys_GetCGameAPI(void* parms)
const char* apppath;
#endif
const char* fn;
const char* gamename = "cgame" ARCH_STRING DLL_EXT;
const char* gamename = "cgame" ARCH_STRING DLL_SUFFIX DLL_EXT;
if (cgame_library)
Com_Error(ERR_FATAL, "Sys_GetCGameAPI without calling Sys_UnloadCGame");