mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 15:21:44 +00:00
Überarbeite sv_send.c
This commit is contained in:
parent
cb0159014d
commit
d899229399
1 changed files with 436 additions and 396 deletions
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue