Überarbeite sv_send.c

This commit is contained in:
Yamagi Burmeister 2010-11-26 08:20:11 +00:00
parent cb0159014d
commit d899229399

View file

@ -1,37 +1,35 @@
/* /*
Copyright (C) 1997-2001 Id Software, Inc. * Copyright (C) 1997-2001 Id Software, Inc.
*
This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or modify
modify it under the terms of the GNU General Public License * it under the terms of the GNU General Public License as published by
as published by the Free Software Foundation; either version 2 * the Free Software Foundation; either version 2 of the License, or (at
of the License, or (at your option) any later version. * your option) any later version.
*
This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful, but
but WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
See the GNU General Public License for more details. * See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Message sending and multiplexing.
*
* =======================================================================
*/ */
// sv_main.c -- server main program
#include "header/server.h" #include "header/server.h"
/*
=============================================================================
Com_Printf redirection
=============================================================================
*/
char sv_outputbuf [ SV_OUTPUTBUF_LENGTH ]; char sv_outputbuf [ SV_OUTPUTBUF_LENGTH ];
void SV_FlushRedirect (int sv_redirected, char *outputbuf) void
SV_FlushRedirect ( int sv_redirected, char *outputbuf )
{ {
if ( sv_redirected == RD_PACKET ) if ( sv_redirected == RD_PACKET )
{ {
@ -45,30 +43,19 @@ void SV_FlushRedirect (int sv_redirected, char *outputbuf)
} }
} }
/* /*
============================================================================= * Sends text across to be displayed if the level passes
EVENT MESSAGES
=============================================================================
*/ */
void
SV_ClientPrintf ( client_t *cl, int level, char *fmt, ... )
/*
=================
SV_ClientPrintf
Sends text across to be displayed if the level passes
=================
*/
void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
{ {
va_list argptr; va_list argptr;
char string [ 1024 ]; char string [ 1024 ];
if ( level < cl->messagelevel ) if ( level < cl->messagelevel )
{
return; return;
}
va_start( argptr, fmt ); va_start( argptr, fmt );
vsprintf( string, fmt, argptr ); vsprintf( string, fmt, argptr );
@ -80,13 +67,10 @@ void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
} }
/* /*
================= * Sends text to all active clients
SV_BroadcastPrintf
Sends text to all active clients
=================
*/ */
void SV_BroadcastPrintf (int level, char *fmt, ...) void
SV_BroadcastPrintf ( int level, char *fmt, ... )
{ {
va_list argptr; va_list argptr;
char string [ 2048 ]; char string [ 2048 ];
@ -97,15 +81,18 @@ void SV_BroadcastPrintf (int level, char *fmt, ...)
vsprintf( string, fmt, argptr ); vsprintf( string, fmt, argptr );
va_end( argptr ); va_end( argptr );
// echo to console /* echo to console */
if ( dedicated->value ) if ( dedicated->value )
{ {
char copy [ 1024 ]; char copy [ 1024 ];
int i; int i;
// mask off high bits /* mask off high bits */
for ( i = 0; i < 1023 && string [ i ]; i++ ) for ( i = 0; i < 1023 && string [ i ]; i++ )
{
copy [ i ] = string [ i ] & 127; copy [ i ] = string [ i ] & 127;
}
copy [ i ] = 0; copy [ i ] = 0;
Com_Printf( "%s", copy ); Com_Printf( "%s", copy );
} }
@ -113,9 +100,15 @@ void SV_BroadcastPrintf (int level, char *fmt, ...)
for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ ) for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
{ {
if ( level < cl->messagelevel ) if ( level < cl->messagelevel )
{
continue; continue;
}
if ( cl->state != cs_spawned ) if ( cl->state != cs_spawned )
{
continue; continue;
}
MSG_WriteByte( &cl->netchan.message, svc_print ); MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, level ); MSG_WriteByte( &cl->netchan.message, level );
MSG_WriteString( &cl->netchan.message, string ); MSG_WriteString( &cl->netchan.message, string );
@ -123,19 +116,19 @@ void SV_BroadcastPrintf (int level, char *fmt, ...)
} }
/* /*
================= * Sends text to all active clients
SV_BroadcastCommand
Sends text to all active clients
=================
*/ */
void SV_BroadcastCommand (char *fmt, ...) void
SV_BroadcastCommand ( char *fmt, ... )
{ {
va_list argptr; va_list argptr;
char string [ 1024 ]; char string [ 1024 ];
if ( !sv.state ) if ( !sv.state )
{
return; return;
}
va_start( argptr, fmt ); va_start( argptr, fmt );
vsprintf( string, fmt, argptr ); vsprintf( string, fmt, argptr );
va_end( argptr ); va_end( argptr );
@ -145,20 +138,16 @@ void SV_BroadcastCommand (char *fmt, ...)
SV_Multicast( NULL, MULTICAST_ALL_R ); SV_Multicast( NULL, MULTICAST_ALL_R );
} }
/* /*
================= * Sends the contents of sv.multicast to a subset of the clients,
SV_Multicast * then clears sv.multicast.
*
Sends the contents of sv.multicast to a subset of the clients, * MULTICAST_ALL same as broadcast (origin can be NULL)
then clears sv.multicast. * MULTICAST_PVS send to clients potentially visible from org
* MULTICAST_PHS send to clients potentially hearable from org
MULTICAST_ALL same as broadcast (origin can be NULL)
MULTICAST_PVS send to clients potentially visible from org
MULTICAST_PHS send to clients potentially hearable from org
=================
*/ */
void SV_Multicast (vec3_t origin, multicast_t to) void
SV_Multicast ( vec3_t origin, multicast_t to )
{ {
client_t *client; client_t *client;
byte *mask; byte *mask;
@ -169,32 +158,34 @@ void SV_Multicast (vec3_t origin, multicast_t to)
reliable = false; reliable = false;
if (to != MULTICAST_ALL_R && to != MULTICAST_ALL) if ( ( to != MULTICAST_ALL_R ) && ( to != MULTICAST_ALL ) )
{ {
leafnum = CM_PointLeafnum( origin ); leafnum = CM_PointLeafnum( origin );
area1 = CM_LeafArea( leafnum ); area1 = CM_LeafArea( leafnum );
} }
else else
{ {
leafnum = 0; // just to avoid compiler warnings leafnum = 0; /* just to avoid compiler warnings */
area1 = 0; area1 = 0;
} }
// if doing a serverrecord, store everything /* if doing a serverrecord, store everything */
if ( svs.demofile ) if ( svs.demofile )
{
SZ_Write( &svs.demo_multicast, sv.multicast.data, sv.multicast.cursize ); SZ_Write( &svs.demo_multicast, sv.multicast.data, sv.multicast.cursize );
}
switch ( to ) switch ( to )
{ {
case MULTICAST_ALL_R: case MULTICAST_ALL_R:
reliable = true; // intentional fallthrough reliable = true; /* intentional fallthrough */
case MULTICAST_ALL: case MULTICAST_ALL:
leafnum = 0; leafnum = 0;
mask = NULL; mask = NULL;
break; break;
case MULTICAST_PHS_R: case MULTICAST_PHS_R:
reliable = true; // intentional fallthrough reliable = true; /* intentional fallthrough */
case MULTICAST_PHS: case MULTICAST_PHS:
leafnum = CM_PointLeafnum( origin ); leafnum = CM_PointLeafnum( origin );
cluster = CM_LeafCluster( leafnum ); cluster = CM_LeafCluster( leafnum );
@ -202,7 +193,7 @@ void SV_Multicast (vec3_t origin, multicast_t to)
break; break;
case MULTICAST_PVS_R: case MULTICAST_PVS_R:
reliable = true; // intentional fallthrough reliable = true; /* intentional fallthrough */
case MULTICAST_PVS: case MULTICAST_PVS:
leafnum = CM_PointLeafnum( origin ); leafnum = CM_PointLeafnum( origin );
cluster = CM_LeafCluster( leafnum ); cluster = CM_LeafCluster( leafnum );
@ -214,64 +205,70 @@ void SV_Multicast (vec3_t origin, multicast_t to)
Com_Error( ERR_FATAL, "SV_Multicast: bad to:%i", to ); Com_Error( ERR_FATAL, "SV_Multicast: bad to:%i", to );
} }
// send the data to all relevent clients /* send the data to all relevent clients */
for ( j = 0, client = svs.clients; j < maxclients->value; j++, client++ ) for ( j = 0, client = svs.clients; j < maxclients->value; j++, client++ )
{ {
if (client->state == cs_free || client->state == cs_zombie) if ( ( client->state == cs_free ) || ( client->state == cs_zombie ) )
{
continue; continue;
if (client->state != cs_spawned && !reliable) }
if ( ( client->state != cs_spawned ) && !reliable )
{
continue; continue;
}
if ( mask ) if ( mask )
{ {
leafnum = CM_PointLeafnum( client->edict->s.origin ); leafnum = CM_PointLeafnum( client->edict->s.origin );
cluster = CM_LeafCluster( leafnum ); cluster = CM_LeafCluster( leafnum );
area2 = CM_LeafArea( leafnum ); area2 = CM_LeafArea( leafnum );
if ( !CM_AreasConnected( area1, area2 ) ) if ( !CM_AreasConnected( area1, area2 ) )
continue; {
if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
continue; continue;
} }
if ( mask && ( !( mask [ cluster >> 3 ] & ( 1 << ( cluster & 7 ) ) ) ) )
{
continue;
}
}
if ( reliable ) if ( reliable )
{
SZ_Write( &client->netchan.message, sv.multicast.data, sv.multicast.cursize ); SZ_Write( &client->netchan.message, sv.multicast.data, sv.multicast.cursize );
}
else else
{
SZ_Write( &client->datagram, sv.multicast.data, sv.multicast.cursize ); SZ_Write( &client->datagram, sv.multicast.data, sv.multicast.cursize );
} }
}
SZ_Clear( &sv.multicast ); SZ_Clear( &sv.multicast );
} }
/* /*
================== * Each entity can have eight independant sound sources, like voice,
SV_StartSound * weapon, feet, etc.
*
Each entity can have eight independant sound sources, like voice, * If cahnnel & 8, the sound will be sent to everyone, not just
weapon, feet, etc. * things in the PHS.
*
If cahnnel & 8, the sound will be sent to everyone, not just * Channel 0 is an auto-allocate channel, the others override anything
things in the PHS. * already running on that entity/channel pair.
*
FIXME: if entity isn't in PHS, they must be forced to be sent or * An attenuation of 0 will play full volume everywhere in the level.
have the origin explicitly sent. * Larger attenuations will drop off. (max 4 attenuation)
*
Channel 0 is an auto-allocate channel, the others override anything * Timeofs can range from 0.0 to 0.1 to cause sounds to be started
already running on that entity/channel pair. * later in the frame than they normally would.
*
An attenuation of 0 will play full volume everywhere in the level. * If origin is NULL, the origin is determined from the entity origin
Larger attenuations will drop off. (max 4 attenuation) * or the midpoint of the entity box for bmodels.
Timeofs can range from 0.0 to 0.1 to cause sounds to be started
later in the frame than they normally would.
If origin is NULL, the origin is determined from the entity origin
or the midpoint of the entity box for bmodels.
==================
*/ */
void SV_StartSound (vec3_t origin, edict_t *entity, int channel, void
int soundindex, float volume, SV_StartSound ( vec3_t origin, edict_t *entity, int channel, int soundindex, float volume, float attenuation, float timeofs )
float attenuation, float timeofs)
{ {
int sendchan; int sendchan;
int flags; int flags;
@ -280,55 +277,76 @@ void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
vec3_t origin_v; vec3_t origin_v;
qboolean use_phs; qboolean use_phs;
if (volume < 0 || volume > 1.0) if ( ( volume < 0 ) || ( volume > 1.0 ) )
{
Com_Error( ERR_FATAL, "SV_StartSound: volume = %f", volume ); Com_Error( ERR_FATAL, "SV_StartSound: volume = %f", volume );
}
if (attenuation < 0 || attenuation > 4) if ( ( attenuation < 0 ) || ( attenuation > 4 ) )
{
Com_Error( ERR_FATAL, "SV_StartSound: attenuation = %f", attenuation ); Com_Error( ERR_FATAL, "SV_StartSound: attenuation = %f", attenuation );
}
if (timeofs < 0 || timeofs > 0.255) if ( ( timeofs < 0 ) || ( timeofs > 0.255 ) )
{
Com_Error( ERR_FATAL, "SV_StartSound: timeofs = %f", timeofs ); Com_Error( ERR_FATAL, "SV_StartSound: timeofs = %f", timeofs );
}
ent = NUM_FOR_EDICT( entity ); ent = NUM_FOR_EDICT( entity );
if (channel & 8) // no PHS flag if ( channel & 8 ) /* no PHS flag */
{ {
use_phs = false; use_phs = false;
channel &= 7; channel &= 7;
} }
else else
{
use_phs = true; use_phs = true;
}
sendchan = ( ent << 3 ) | ( channel & 7 ); sendchan = ( ent << 3 ) | ( channel & 7 );
flags = 0; flags = 0;
if ( volume != DEFAULT_SOUND_PACKET_VOLUME ) if ( volume != DEFAULT_SOUND_PACKET_VOLUME )
{
flags |= SND_VOLUME; flags |= SND_VOLUME;
}
if ( attenuation != DEFAULT_SOUND_PACKET_ATTENUATION ) if ( attenuation != DEFAULT_SOUND_PACKET_ATTENUATION )
{
flags |= SND_ATTENUATION; flags |= SND_ATTENUATION;
}
// the client doesn't know that bmodels have weird origins /* the client doesn't know that bmodels have weird origins
// the origin can also be explicitly set the origin can also be explicitly set */
if ( (entity->svflags & SVF_NOCLIENT) if ( ( entity->svflags & SVF_NOCLIENT ) ||
|| (entity->solid == SOLID_BSP) ( entity->solid == SOLID_BSP ) ||
|| origin ) origin )
{
flags |= SND_POS; flags |= SND_POS;
}
// always send the entity number for channel overrides /* always send the entity number for channel overrides */
flags |= SND_ENT; flags |= SND_ENT;
if ( timeofs ) if ( timeofs )
{
flags |= SND_OFFSET; flags |= SND_OFFSET;
}
// use the entity origin unless it is a bmodel or explicitly specified /* use the entity origin unless it is a bmodel or explicitly specified */
if ( !origin ) if ( !origin )
{ {
origin = origin_v; origin = origin_v;
if ( entity->solid == SOLID_BSP ) if ( entity->solid == SOLID_BSP )
{ {
for ( i = 0; i < 3; i++ ) for ( i = 0; i < 3; i++ )
{
origin_v [ i ] = entity->s.origin [ i ] + 0.5f * ( entity->mins [ i ] + entity->maxs [ i ] ); origin_v [ i ] = entity->s.origin [ i ] + 0.5f * ( entity->mins [ i ] + entity->maxs [ i ] );
} }
}
else else
{ {
VectorCopy( entity->s.origin, origin_v ); VectorCopy( entity->s.origin, origin_v );
@ -340,56 +358,63 @@ void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
MSG_WriteByte( &sv.multicast, soundindex ); MSG_WriteByte( &sv.multicast, soundindex );
if ( flags & SND_VOLUME ) if ( flags & SND_VOLUME )
{
MSG_WriteByte( &sv.multicast, volume * 255 ); MSG_WriteByte( &sv.multicast, volume * 255 );
}
if ( flags & SND_ATTENUATION ) if ( flags & SND_ATTENUATION )
{
MSG_WriteByte( &sv.multicast, attenuation * 64 ); MSG_WriteByte( &sv.multicast, attenuation * 64 );
}
if ( flags & SND_OFFSET ) if ( flags & SND_OFFSET )
{
MSG_WriteByte( &sv.multicast, timeofs * 1000 ); MSG_WriteByte( &sv.multicast, timeofs * 1000 );
}
if ( flags & SND_ENT ) if ( flags & SND_ENT )
{
MSG_WriteShort( &sv.multicast, sendchan ); MSG_WriteShort( &sv.multicast, sendchan );
}
if ( flags & SND_POS ) if ( flags & SND_POS )
{
MSG_WritePos( &sv.multicast, origin ); MSG_WritePos( &sv.multicast, origin );
}
// if the sound doesn't attenuate,send it to everyone /* if the sound doesn't attenuate,send it to everyone
// (global radio chatter, voiceovers, etc) (global radio chatter, voiceovers, etc) */
if ( attenuation == ATTN_NONE ) if ( attenuation == ATTN_NONE )
{
use_phs = false; use_phs = false;
}
if ( channel & CHAN_RELIABLE ) if ( channel & CHAN_RELIABLE )
{ {
if ( use_phs ) if ( use_phs )
{
SV_Multicast( origin, MULTICAST_PHS_R ); SV_Multicast( origin, MULTICAST_PHS_R );
}
else else
{
SV_Multicast( origin, MULTICAST_ALL_R ); SV_Multicast( origin, MULTICAST_ALL_R );
} }
}
else else
{ {
if ( use_phs ) if ( use_phs )
{
SV_Multicast( origin, MULTICAST_PHS ); SV_Multicast( origin, MULTICAST_PHS );
}
else else
{
SV_Multicast( origin, MULTICAST_ALL ); SV_Multicast( origin, MULTICAST_ALL );
} }
} }
}
qboolean
/* SV_SendClientDatagram ( client_t *client )
===============================================================================
FRAME UPDATES
===============================================================================
*/
/*
=======================
SV_SendClientDatagram
=======================
*/
qboolean SV_SendClientDatagram (client_t *client)
{ {
byte msg_buf [ MAX_MSGLEN ]; byte msg_buf [ MAX_MSGLEN ];
sizebuf_t msg; sizebuf_t msg;
@ -399,68 +424,68 @@ qboolean SV_SendClientDatagram (client_t *client)
SZ_Init( &msg, msg_buf, sizeof ( msg_buf ) ); SZ_Init( &msg, msg_buf, sizeof ( msg_buf ) );
msg.allowoverflow = true; msg.allowoverflow = true;
// send over all the relevant entity_state_t /* send over all the relevant entity_state_t
// and the player_state_t and the player_state_t */
SV_WriteFrameToClient( client, &msg ); SV_WriteFrameToClient( client, &msg );
// copy the accumulated multicast datagram /* copy the accumulated multicast datagram
// for this client out to the message for this client out to the message
// it is necessary for this to be after the WriteEntities it is necessary for this to be after the WriteEntities
// so that entity references will be current so that entity references will be current */
if ( client->datagram.overflowed ) if ( client->datagram.overflowed )
{
Com_Printf( "WARNING: datagram overflowed for %s\n", client->name ); Com_Printf( "WARNING: datagram overflowed for %s\n", client->name );
}
else else
{
SZ_Write( &msg, client->datagram.data, client->datagram.cursize ); SZ_Write( &msg, client->datagram.data, client->datagram.cursize );
}
SZ_Clear( &client->datagram ); SZ_Clear( &client->datagram );
if ( msg.overflowed ) if ( msg.overflowed )
{ // must have room left for the packet header {
/* must have room left for the packet header */
Com_Printf( "WARNING: msg overflowed for %s\n", client->name ); Com_Printf( "WARNING: msg overflowed for %s\n", client->name );
SZ_Clear( &msg ); SZ_Clear( &msg );
} }
// send the datagram /* send the datagram */
Netchan_Transmit( &client->netchan, msg.cursize, msg.data ); Netchan_Transmit( &client->netchan, msg.cursize, msg.data );
// record the size for rate estimation /* record the size for rate estimation */
client->message_size [ sv.framenum % RATE_MESSAGES ] = msg.cursize; client->message_size [ sv.framenum % RATE_MESSAGES ] = msg.cursize;
return true; return ( true );
} }
void
/* SV_DemoCompleted ( void )
==================
SV_DemoCompleted
==================
*/
void SV_DemoCompleted (void)
{ {
if ( sv.demofile ) if ( sv.demofile )
{ {
FS_FCloseFile( (size_t) sv.demofile ); FS_FCloseFile( (size_t) sv.demofile );
sv.demofile = NULL; sv.demofile = NULL;
} }
SV_Nextserver(); SV_Nextserver();
} }
/* /*
======================= * Returns true if the client is over its current
SV_RateDrop * bandwidth estimation and should not be sent another packet
Returns true if the client is over its current
bandwidth estimation and should not be sent another packet
=======================
*/ */
qboolean SV_RateDrop (client_t *c) qboolean
SV_RateDrop ( client_t *c )
{ {
int total; int total;
int i; int i;
// never drop over the loopback /* never drop over the loopback */
if ( c->netchan.remote_address.type == NA_LOOPBACK ) if ( c->netchan.remote_address.type == NA_LOOPBACK )
return false; {
return ( false );
}
total = 0; total = 0;
@ -473,18 +498,14 @@ qboolean SV_RateDrop (client_t *c)
{ {
c->surpressCount++; c->surpressCount++;
c->message_size [ sv.framenum % RATE_MESSAGES ] = 0; c->message_size [ sv.framenum % RATE_MESSAGES ] = 0;
return true; return ( true );
} }
return false; return ( false );
} }
/* void
======================= SV_SendClientMessages ( void )
SV_SendClientMessages
=======================
*/
void SV_SendClientMessages (void)
{ {
int i; int i;
client_t *c; client_t *c;
@ -494,29 +515,39 @@ void SV_SendClientMessages (void)
msglen = 0; msglen = 0;
// read the next demo message if needed /* read the next demo message if needed */
if (sv.demofile && sv.state == ss_demo) if ( sv.demofile && ( sv.state == ss_demo ) )
{ {
if ( sv_paused->value ) if ( sv_paused->value )
{
msglen = 0; msglen = 0;
}
else else
{ {
// get the next message /* get the next message */
r = FS_FRead( &msglen, 4, 1, (size_t) sv.demofile ); r = FS_FRead( &msglen, 4, 1, (size_t) sv.demofile );
if ( r != 4 ) if ( r != 4 )
{ {
SV_DemoCompleted(); SV_DemoCompleted();
return; return;
} }
msglen = LittleLong( msglen ); msglen = LittleLong( msglen );
if ( msglen == -1 ) if ( msglen == -1 )
{ {
SV_DemoCompleted(); SV_DemoCompleted();
return; return;
} }
if ( msglen > MAX_MSGLEN ) if ( msglen > MAX_MSGLEN )
{
Com_Error( ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN" ); Com_Error( ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN" );
}
r = FS_FRead( msgbuf, msglen, 1, (size_t) sv.demofile ); r = FS_FRead( msgbuf, msglen, 1, (size_t) sv.demofile );
if ( r != msglen ) if ( r != msglen )
{ {
SV_DemoCompleted(); SV_DemoCompleted();
@ -525,13 +556,16 @@ void SV_SendClientMessages (void)
} }
} }
// send a message to each connected client /* send a message to each connected client */
for ( i = 0, c = svs.clients; i < maxclients->value; i++, c++ ) for ( i = 0, c = svs.clients; i < maxclients->value; i++, c++ )
{ {
if ( !c->state ) if ( !c->state )
{
continue; continue;
// if the reliable message overflowed, }
// drop the client
/* if the reliable message overflowed,
drop the client */
if ( c->netchan.message.overflowed ) if ( c->netchan.message.overflowed )
{ {
SZ_Clear( &c->netchan.message ); SZ_Clear( &c->netchan.message );
@ -540,25 +574,31 @@ void SV_SendClientMessages (void)
SV_DropClient( c ); SV_DropClient( c );
} }
if (sv.state == ss_cinematic if ( ( sv.state == ss_cinematic ) ||
|| sv.state == ss_demo ( sv.state == ss_demo ) ||
|| sv.state == ss_pic ( sv.state == ss_pic )
) )
{
Netchan_Transmit( &c->netchan, msglen, msgbuf ); Netchan_Transmit( &c->netchan, msglen, msgbuf );
}
else if ( c->state == cs_spawned ) else if ( c->state == cs_spawned )
{ {
// don't overrun bandwidth /* don't overrun bandwidth */
if ( SV_RateDrop( c ) ) if ( SV_RateDrop( c ) )
{
continue; continue;
}
SV_SendClientDatagram( c ); SV_SendClientDatagram( c );
} }
else else
{ {
// just update reliable if needed /* just update reliable if needed */
if (c->netchan.message.cursize || curtime - c->netchan.last_sent > 1000 ) if ( c->netchan.message.cursize || ( curtime - c->netchan.last_sent > 1000 ) )
{
Netchan_Transmit( &c->netchan, 0, NULL ); Netchan_Transmit( &c->netchan, 0, NULL );
} }
} }
} }
}