diff options
author | Tim Angus <tim@ngus.net> | 2011-04-23 22:38:25 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-03 00:18:07 +0000 |
commit | 06006eb6930de74c577c87daf6a0f7917e22d578 (patch) | |
tree | 8caec25df040a3f3eddc99b593e51d993b9be1be /src/server | |
parent | 98438cc3e7d32312bb52b413c12698b67b8cfeb0 (diff) |
* Merge ioq3-r1946
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/server.h | 10 | ||||
-rw-r--r-- | src/server/sv_ccmds.c | 16 | ||||
-rw-r--r-- | src/server/sv_client.c | 34 | ||||
-rw-r--r-- | src/server/sv_game.c | 4 | ||||
-rw-r--r-- | src/server/sv_init.c | 18 | ||||
-rw-r--r-- | src/server/sv_main.c | 56 | ||||
-rw-r--r-- | src/server/sv_snapshot.c | 12 |
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)); } } |