summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2011-04-23 22:38:25 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:18:07 +0000
commit06006eb6930de74c577c87daf6a0f7917e22d578 (patch)
tree8caec25df040a3f3eddc99b593e51d993b9be1be /src/server
parent98438cc3e7d32312bb52b413c12698b67b8cfeb0 (diff)
* Merge ioq3-r1946
Diffstat (limited to 'src/server')
-rw-r--r--src/server/server.h10
-rw-r--r--src/server/sv_ccmds.c16
-rw-r--r--src/server/sv_client.c34
-rw-r--r--src/server/sv_game.c4
-rw-r--r--src/server/sv_init.c18
-rw-r--r--src/server/sv_main.c56
-rw-r--r--src/server/sv_snapshot.c12
7 files changed, 82 insertions, 68 deletions
diff --git a/src/server/server.h b/src/server/server.h
index ad9fcde4..0475f0b9 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -220,10 +220,6 @@ typedef struct {
qboolean connected;
} challenge_t;
-
-#define MAX_MASTERS 8 // max recipients for heartbeat packets
-
-
// this structure will be cleared only when the game dll changes
typedef struct {
qboolean initialized; // sv_init has completed
@@ -249,8 +245,6 @@ extern serverStatic_t svs; // persistant server info across maps
extern server_t sv; // cleared each map
extern vm_t *gvm; // game virtual machine
-#define MAX_MASTER_SERVERS 5
-
extern cvar_t *sv_fps;
extern cvar_t *sv_timeout;
extern cvar_t *sv_zombietime;
@@ -276,6 +270,8 @@ extern cvar_t *sv_maxPing;
extern cvar_t *sv_pure;
extern cvar_t *sv_lanForceRate;
extern cvar_t *sv_dequeuePeriod;
+extern cvar_t *sv_heartbeat;
+extern cvar_t *sv_flatline;
#ifdef USE_VOIP
extern cvar_t *sv_voip;
@@ -295,13 +291,11 @@ void SV_AddOperatorCommands (void);
void SV_RemoveOperatorCommands (void);
-void SV_MasterHeartbeat (void);
void SV_MasterShutdown (void);
void SV_MasterGameStat( const char *data );
-
//
// sv_init.c
//
diff --git a/src/server/sv_ccmds.c b/src/server/sv_ccmds.c
index 6768bb9c..8e76fa1f 100644
--- a/src/server/sv_ccmds.c
+++ b/src/server/sv_ccmds.c
@@ -205,9 +205,15 @@ static void SV_MapRestart_f( void ) {
continue;
}
- client->state = CS_ACTIVE;
-
- SV_ClientEnterWorld( client, &client->lastUsercmd );
+ if(client->state == CS_ACTIVE)
+ SV_ClientEnterWorld(client, &client->lastUsercmd);
+ else
+ {
+ // If we don't reset client->lastUsercmd and are restarting during map load,
+ // the client will hang because we'll use the last Usercmd from the previous map,
+ // which is wrong obviously.
+ SV_ClientEnterWorld(client, NULL);
+ }
}
// run another frame to allow things to look at all the players
@@ -251,7 +257,7 @@ Examine or change the serverinfo string
*/
static void SV_Systeminfo_f( void ) {
Com_Printf ("System info settings:\n");
- Info_Print ( Cvar_InfoString( CVAR_SYSTEMINFO ) );
+ Info_Print ( Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );
}
@@ -273,7 +279,7 @@ SV_CompleteMapName
*/
static void SV_CompleteMapName( char *args, int argNum ) {
if( argNum == 2 ) {
- Field_CompleteFilename( "maps", "bsp", qtrue );
+ Field_CompleteFilename( "maps", "bsp", qtrue, qfalse );
}
}
diff --git a/src/server/sv_client.c b/src/server/sv_client.c
index 815bf4db..a79fc2bc 100644
--- a/src/server/sv_client.c
+++ b/src/server/sv_client.c
@@ -505,7 +505,11 @@ void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ) {
client->deltaMessage = -1;
client->nextSnapshotTime = svs.time; // generate a snapshot immediately
- client->lastUsercmd = *cmd;
+
+ if(cmd)
+ memcpy(&client->lastUsercmd, cmd, sizeof(client->lastUsercmd));
+ else
+ memset(&client->lastUsercmd, '\0', sizeof(client->lastUsercmd));
// call the game begin function
VM_Call( gvm, GAME_CLIENT_BEGIN, client - svs.clients );
@@ -633,7 +637,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
int curindex;
int rate;
int blockspersnap;
- int idPack = 0, missionPack = 0, unreferenced = 1;
+ int unreferenced = 1;
char errorMessage[1024];
char pakbuf[MAX_QPATH], *pakptr;
int numRefPaks;
@@ -641,7 +645,8 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
if (!*cl->downloadName)
return; // Nothing being downloaded
- if (!cl->download) {
+ if(!cl->download)
+ {
// Chop off filename extension.
Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName);
pakptr = Q_strrchr(pakbuf, '.');
@@ -665,12 +670,6 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
if(!FS_FilenameCompare(Cmd_Argv(curindex), pakbuf))
{
unreferenced = 0;
-
- // now that we know the file is referenced,
- // check whether it's legal to download it.
- missionPack = FS_idPak(pakbuf, "missionpack");
- idPack = missionPack || FS_idPak(pakbuf, BASEGAME);
-
break;
}
}
@@ -682,7 +681,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
// We open the file here
if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
(sv_allowDownload->integer & DLF_NO_UDP) ||
- idPack || unreferenced ||
+ unreferenced ||
( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) < 0 ) {
// cannot auto-download file
if(unreferenced)
@@ -690,16 +689,6 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
Com_Printf("clientDownload: %d : \"%s\" is not referenced and cannot be downloaded.\n", (int) (cl - svs.clients), cl->downloadName);
Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName);
}
- else if (idPack) {
- Com_Printf("clientDownload: %d : \"%s\" cannot download id pk3 files\n", (int) (cl - svs.clients), cl->downloadName);
- if (missionPack) {
- Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Team Arena file \"%s\"\n"
- "The Team Arena mission pack can be found in your local game store.", cl->downloadName);
- }
- else {
- Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName);
- }
- }
else if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
(sv_allowDownload->integer & DLF_NO_UDP) ) {
@@ -1272,7 +1261,8 @@ void SV_ExecuteClientCommand( client_t *cl, const char *s, qboolean clientOK ) {
if (clientOK) {
// pass unknown strings to the game
- if (!u->name && sv.state == SS_GAME && cl->state == CS_ACTIVE) {
+ if (!u->name && sv.state == SS_GAME && (cl->state == CS_ACTIVE || cl->state == CS_PRIMED)) {
+ Cmd_Args_Sanitize();
VM_Call( gvm, GAME_CLIENT_COMMAND, cl - svs.clients );
}
}
@@ -1560,7 +1550,7 @@ void SV_UserVoip( client_t *cl, msg_t *msg ) {
// Transmit this packet to the client.
// !!! FIXME: I don't like this queueing system.
- if (client->queuedVoipPackets >= (sizeof (client->voipPacket) / sizeof (client->voipPacket[0]))) {
+ if (client->queuedVoipPackets >= ARRAY_LEN(client->voipPacket)) {
Com_Printf("Too many VoIP packets queued for client #%d\n", i);
continue; // no room for another packet right now.
}
diff --git a/src/server/sv_game.c b/src/server/sv_game.c
index efd6265e..e6c98f9c 100644
--- a/src/server/sv_game.c
+++ b/src/server/sv_game.c
@@ -216,7 +216,7 @@ void SV_AdjustAreaPortalState( sharedEntity_t *ent, qboolean open ) {
/*
==================
-SV_GameAreaEntities
+SV_EntityContact
==================
*/
qboolean SV_EntityContact( vec3_t mins, vec3_t maxs, const sharedEntity_t *gEnt, traceType_t type ) {
@@ -311,7 +311,7 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) {
Cvar_Update( VMA(1) );
return 0;
case G_CVAR_SET:
- Cvar_Set( (const char *)VMA(1), (const char *)VMA(2) );
+ Cvar_SetSafe( (const char *)VMA(1), (const char *)VMA(2) );
return 0;
case G_CVAR_VARIABLE_INTEGER_VALUE:
return Cvar_VariableIntegerValue( (const char *)VMA(1) );
diff --git a/src/server/sv_init.c b/src/server/sv_init.c
index 59e03464..e84ff0f4 100644
--- a/src/server/sv_init.c
+++ b/src/server/sv_init.c
@@ -618,13 +618,15 @@ SV_Init
Only called at main exe startup, not for each game
===============
*/
-void SV_Init (void) {
+void SV_Init (void)
+{
+ int index;
+
SV_AddOperatorCommands ();
// serverinfo vars
Cvar_Get ("timelimit", "0", CVAR_SERVERINFO);
Cvar_Get ("sv_keywords", "", CVAR_SERVERINFO);
- Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_ROM);
sv_mapname = Cvar_Get ("mapname", "nomap", CVAR_SERVERINFO | CVAR_ROM);
sv_privateClients = Cvar_Get ("sv_privateClients", "0", CVAR_SERVERINFO);
sv_hostname = Cvar_Get ("sv_hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE );
@@ -657,11 +659,11 @@ void SV_Init (void) {
sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO);
Cvar_Get ("sv_dlURL", "http://downloads.tremulous.net", CVAR_SERVERINFO | CVAR_ARCHIVE);
- sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 );
- sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE );
- sv_master[2] = Cvar_Get ("sv_master3", "", CVAR_ARCHIVE );
- sv_master[3] = Cvar_Get ("sv_master4", "", CVAR_ARCHIVE );
- sv_master[4] = Cvar_Get ("sv_master5", "", CVAR_ARCHIVE );
+
+ sv_master[0] = Cvar_Get("sv_master1", MASTER_SERVER_NAME, 0);
+ for(index = 1; index < MAX_MASTER_SERVERS; index++)
+ sv_master[index] = Cvar_Get(va("sv_master%d", index + 1), "", CVAR_ARCHIVE);
+
sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0);
sv_showloss = Cvar_Get ("sv_showloss", "0", 0);
sv_padPackets = Cvar_Get ("sv_padPackets", "0", 0);
@@ -669,6 +671,8 @@ void SV_Init (void) {
sv_mapChecksum = Cvar_Get ("sv_mapChecksum", "", CVAR_ROM);
sv_lanForceRate = Cvar_Get ("sv_lanForceRate", "1", CVAR_ARCHIVE );
sv_dequeuePeriod = Cvar_Get ("sv_dequeuePeriod", "500", CVAR_ARCHIVE );
+ sv_heartbeat = Cvar_Get("sv_heartbeat", HEARTBEAT_FOR_MASTER, CVAR_INIT);
+ sv_flatline = Cvar_Get("sv_flatline", FLATLINE_FOR_MASTER, CVAR_INIT);
}
diff --git a/src/server/sv_main.c b/src/server/sv_main.c
index fa009b62..014c3a96 100644
--- a/src/server/sv_main.c
+++ b/src/server/sv_main.c
@@ -31,17 +31,17 @@ serverStatic_t svs; // persistant server info
server_t sv; // local server
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_zombietime; // seconds to sink messages after disconnect
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_maxclients;
cvar_t *sv_privateClients; // number of clients reserved for password
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_showloss; // report when usercmds are lost
cvar_t *sv_padPackets; // add nop bytes to messages
@@ -56,6 +56,9 @@ cvar_t *sv_maxPing;
cvar_t *sv_pure;
cvar_t *sv_lanForceRate; // dedicated 1 (LAN) server forces local client rates to 99999 (bug #491)
cvar_t *sv_dequeuePeriod;
+cvar_t *sv_heartbeat; // Heartbeat string that is sent to the master
+cvar_t *sv_flatline; // If the master server supports it we can send a flatline
+ // when server is killed
/*
=============================================================================
@@ -221,8 +224,8 @@ but not on every player enter or exit.
================
*/
#define HEARTBEAT_MSEC 300*1000
-#define HEARTBEAT_GAME "Tremulous"
-void SV_MasterHeartbeat( void ) {
+void SV_MasterHeartbeat(const char *message)
+{
static netadr_t adr[MAX_MASTER_SERVERS][2]; // [2] for v4 and v6 address for the same address string.
int i;
int res;
@@ -303,9 +306,9 @@ void SV_MasterHeartbeat( void ) {
// ever incompatably changes
if(adr[i][0].type != NA_BAD)
- NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", HEARTBEAT_GAME );
+ NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", message);
if(adr[i][1].type != NA_BAD)
- NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", HEARTBEAT_GAME );
+ NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", message);
}
}
@@ -319,11 +322,11 @@ Informs all masters that this server is going down
void SV_MasterShutdown( void ) {
// send a hearbeat right now
svs.nextHeartbeatTime = -9999;
- SV_MasterHeartbeat();
+ SV_MasterHeartbeat(sv_flatline->string);
// send it again to minimize chance of drops
svs.nextHeartbeatTime = -9999;
- SV_MasterHeartbeat();
+ SV_MasterHeartbeat(sv_flatline->string);
// when the master tries to poll the server, it won't respond, so
// it will be removed from the list
@@ -460,7 +463,8 @@ static leakyBucket_t *SVC_BucketForAddress( netadr_t address, int burst, int per
interval = now - bucket->lastTime;
// Reclaim expired buckets
- if ( bucket->lastTime > 0 && interval > ( burst * period ) ) {
+ if ( bucket->lastTime > 0 && ( interval > ( burst * period ) ||
+ interval < 0 ) ) {
if ( bucket->prev != NULL ) {
bucket->prev->next = bucket->next;
} else {
@@ -1003,6 +1007,29 @@ static qboolean SV_CheckPaused( void ) {
/*
==================
+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
Player movement occurs as a result of packet events, which
@@ -1051,13 +1078,6 @@ void SV_Frame( int msec ) {
sv.timeResidual += msec;
- 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
// and clear sv.time, rather
// than checking for negative time wraparound everywhere.
@@ -1120,7 +1140,7 @@ void SV_Frame( int msec ) {
SV_SendClientMessages();
// send a heartbeat to the master if needed
- SV_MasterHeartbeat();
+ SV_MasterHeartbeat(sv_heartbeat->string);
}
//============================================================================
diff --git a/src/server/sv_snapshot.c b/src/server/sv_snapshot.c
index bbd1fc01..cfc56958 100644
--- a/src/server/sv_snapshot.c
+++ b/src/server/sv_snapshot.c
@@ -351,7 +351,7 @@ static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *fra
// entities can be flagged to be sent to a given mask of clients
if ( ent->r.svFlags & SVF_CLIENTMASK ) {
if (frame->ps.clientNum >= 32)
- Com_Error( ERR_DROP, "SVF_CLIENTMASK: cientNum > 32\n" );
+ Com_Error( ERR_DROP, "SVF_CLIENTMASK: clientNum >= 32\n" );
if (~ent->r.singleClient & (1 << frame->ps.clientNum))
continue;
}
@@ -556,7 +556,7 @@ static int SV_RateMsec( client_t *client, int messageSize ) {
rate = sv_minRate->integer;
}
- rateMsec = ( messageSize + HEADER_RATE_BYTES ) * 1000 / rate * com_timescale->value;
+ rateMsec = ( messageSize + HEADER_RATE_BYTES ) * 1000 / ((int) (rate * com_timescale->value));
return rateMsec;
}
@@ -585,7 +585,7 @@ void SV_SendMessageToClient( msg_t *msg, client_t *client ) {
// TTimo - https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
// added sv_lanForceRate check
if ( client->netchan.remoteAddress.type == NA_LOOPBACK || (sv_lanForceRate->integer && Sys_IsLANAddress (client->netchan.remoteAddress)) ) {
- client->nextSnapshotTime = svs.time + (1000.0 / sv_fps->integer * com_timescale->value);
+ client->nextSnapshotTime = svs.time + ((int) (1000.0 / sv_fps->integer * com_timescale->value));
return;
}
@@ -600,15 +600,15 @@ void SV_SendMessageToClient( msg_t *msg, client_t *client ) {
client->rateDelayed = qtrue;
}
- client->nextSnapshotTime = svs.time + rateMsec * com_timescale->value;
+ client->nextSnapshotTime = svs.time + ((int) (rateMsec * com_timescale->value));
// don't pile up empty snapshots while connecting
if ( client->state != CS_ACTIVE ) {
// a gigantic connection message may have already put the nextSnapshotTime
// more than a second away, so don't shorten it
// do shorten if client is downloading
- if (!*client->downloadName && client->nextSnapshotTime < svs.time + 1000 * com_timescale->value)
- client->nextSnapshotTime = svs.time + 1000 * com_timescale->value;
+ if (!*client->downloadName && client->nextSnapshotTime < svs.time + ((int) (1000.0 * com_timescale->value)))
+ client->nextSnapshotTime = svs.time + ((int) (1000 * com_timescale->value));
}
}