Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

sv_send.c (12612B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // sv_main.c -- server main program
     21 
     22 #include "server.h"
     23 
     24 /*
     25 =============================================================================
     26 
     27 Com_Printf redirection
     28 
     29 =============================================================================
     30 */
     31 
     32 char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
     33 
     34 void SV_FlushRedirect (int sv_redirected, char *outputbuf)
     35 {
     36 	if (sv_redirected == RD_PACKET)
     37 	{
     38 		Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", outputbuf);
     39 	}
     40 	else if (sv_redirected == RD_CLIENT)
     41 	{
     42 		MSG_WriteByte (&sv_client->netchan.message, svc_print);
     43 		MSG_WriteByte (&sv_client->netchan.message, PRINT_HIGH);
     44 		MSG_WriteString (&sv_client->netchan.message, outputbuf);
     45 	}
     46 }
     47 
     48 
     49 /*
     50 =============================================================================
     51 
     52 EVENT MESSAGES
     53 
     54 =============================================================================
     55 */
     56 
     57 
     58 /*
     59 =================
     60 SV_ClientPrintf
     61 
     62 Sends text across to be displayed if the level passes
     63 =================
     64 */
     65 void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
     66 {
     67 	va_list		argptr;
     68 	char		string[1024];
     69 	
     70 	if (level < cl->messagelevel)
     71 		return;
     72 	
     73 	va_start (argptr,fmt);
     74 	vsprintf (string, fmt,argptr);
     75 	va_end (argptr);
     76 	
     77 	MSG_WriteByte (&cl->netchan.message, svc_print);
     78 	MSG_WriteByte (&cl->netchan.message, level);
     79 	MSG_WriteString (&cl->netchan.message, string);
     80 }
     81 
     82 /*
     83 =================
     84 SV_BroadcastPrintf
     85 
     86 Sends text to all active clients
     87 =================
     88 */
     89 void SV_BroadcastPrintf (int level, char *fmt, ...)
     90 {
     91 	va_list		argptr;
     92 	char		string[2048];
     93 	client_t	*cl;
     94 	int			i;
     95 
     96 	va_start (argptr,fmt);
     97 	vsprintf (string, fmt,argptr);
     98 	va_end (argptr);
     99 	
    100 	// echo to console
    101 	if (dedicated->value)
    102 	{
    103 		char	copy[1024];
    104 		int		i;
    105 		
    106 		// mask off high bits
    107 		for (i=0 ; i<1023 && string[i] ; i++)
    108 			copy[i] = string[i]&127;
    109 		copy[i] = 0;
    110 		Com_Printf ("%s", copy);
    111 	}
    112 
    113 	for (i=0, cl = svs.clients ; i<maxclients->value; i++, cl++)
    114 	{
    115 		if (level < cl->messagelevel)
    116 			continue;
    117 		if (cl->state != cs_spawned)
    118 			continue;
    119 		MSG_WriteByte (&cl->netchan.message, svc_print);
    120 		MSG_WriteByte (&cl->netchan.message, level);
    121 		MSG_WriteString (&cl->netchan.message, string);
    122 	}
    123 }
    124 
    125 /*
    126 =================
    127 SV_BroadcastCommand
    128 
    129 Sends text to all active clients
    130 =================
    131 */
    132 void SV_BroadcastCommand (char *fmt, ...)
    133 {
    134 	va_list		argptr;
    135 	char		string[1024];
    136 	
    137 	if (!sv.state)
    138 		return;
    139 	va_start (argptr,fmt);
    140 	vsprintf (string, fmt,argptr);
    141 	va_end (argptr);
    142 
    143 	MSG_WriteByte (&sv.multicast, svc_stufftext);
    144 	MSG_WriteString (&sv.multicast, string);
    145 	SV_Multicast (NULL, MULTICAST_ALL_R);
    146 }
    147 
    148 
    149 /*
    150 =================
    151 SV_Multicast
    152 
    153 Sends the contents of sv.multicast to a subset of the clients,
    154 then clears sv.multicast.
    155 
    156 MULTICAST_ALL	same as broadcast (origin can be NULL)
    157 MULTICAST_PVS	send to clients potentially visible from org
    158 MULTICAST_PHS	send to clients potentially hearable from org
    159 =================
    160 */
    161 void SV_Multicast (vec3_t origin, multicast_t to)
    162 {
    163 	client_t	*client;
    164 	byte		*mask;
    165 	int			leafnum, cluster;
    166 	int			j;
    167 	qboolean	reliable;
    168 	int			area1, area2;
    169 
    170 	reliable = false;
    171 
    172 	if (to != MULTICAST_ALL_R && to != MULTICAST_ALL)
    173 	{
    174 		leafnum = CM_PointLeafnum (origin);
    175 		area1 = CM_LeafArea (leafnum);
    176 	}
    177 	else
    178 	{
    179 		leafnum = 0;	// just to avoid compiler warnings
    180 		area1 = 0;
    181 	}
    182 
    183 	// if doing a serverrecord, store everything
    184 	if (svs.demofile)
    185 		SZ_Write (&svs.demo_multicast, sv.multicast.data, sv.multicast.cursize);
    186 	
    187 	switch (to)
    188 	{
    189 	case MULTICAST_ALL_R:
    190 		reliable = true;	// intentional fallthrough
    191 	case MULTICAST_ALL:
    192 		leafnum = 0;
    193 		mask = NULL;
    194 		break;
    195 
    196 	case MULTICAST_PHS_R:
    197 		reliable = true;	// intentional fallthrough
    198 	case MULTICAST_PHS:
    199 		leafnum = CM_PointLeafnum (origin);
    200 		cluster = CM_LeafCluster (leafnum);
    201 		mask = CM_ClusterPHS (cluster);
    202 		break;
    203 
    204 	case MULTICAST_PVS_R:
    205 		reliable = true;	// intentional fallthrough
    206 	case MULTICAST_PVS:
    207 		leafnum = CM_PointLeafnum (origin);
    208 		cluster = CM_LeafCluster (leafnum);
    209 		mask = CM_ClusterPVS (cluster);
    210 		break;
    211 
    212 	default:
    213 		mask = NULL;
    214 		Com_Error (ERR_FATAL, "SV_Multicast: bad to:%i", to);
    215 	}
    216 
    217 	// send the data to all relevent clients
    218 	for (j = 0, client = svs.clients; j < maxclients->value; j++, client++)
    219 	{
    220 		if (client->state == cs_free || client->state == cs_zombie)
    221 			continue;
    222 		if (client->state != cs_spawned && !reliable)
    223 			continue;
    224 
    225 		if (mask)
    226 		{
    227 			leafnum = CM_PointLeafnum (client->edict->s.origin);
    228 			cluster = CM_LeafCluster (leafnum);
    229 			area2 = CM_LeafArea (leafnum);
    230 			if (!CM_AreasConnected (area1, area2))
    231 				continue;
    232 			if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
    233 				continue;
    234 		}
    235 
    236 		if (reliable)
    237 			SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize);
    238 		else
    239 			SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
    240 	}
    241 
    242 	SZ_Clear (&sv.multicast);
    243 }
    244 
    245 
    246 /*  
    247 ==================
    248 SV_StartSound
    249 
    250 Each entity can have eight independant sound sources, like voice,
    251 weapon, feet, etc.
    252 
    253 If cahnnel & 8, the sound will be sent to everyone, not just
    254 things in the PHS.
    255 
    256 FIXME: if entity isn't in PHS, they must be forced to be sent or
    257 have the origin explicitly sent.
    258 
    259 Channel 0 is an auto-allocate channel, the others override anything
    260 already running on that entity/channel pair.
    261 
    262 An attenuation of 0 will play full volume everywhere in the level.
    263 Larger attenuations will drop off.  (max 4 attenuation)
    264 
    265 Timeofs can range from 0.0 to 0.1 to cause sounds to be started
    266 later in the frame than they normally would.
    267 
    268 If origin is NULL, the origin is determined from the entity origin
    269 or the midpoint of the entity box for bmodels.
    270 ==================
    271 */  
    272 void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
    273 					int soundindex, float volume,
    274 					float attenuation, float timeofs)
    275 {       
    276 	int			sendchan;
    277     int			flags;
    278     int			i;
    279 	int			ent;
    280 	vec3_t		origin_v;
    281 	qboolean	use_phs;
    282 
    283 	if (volume < 0 || volume > 1.0)
    284 		Com_Error (ERR_FATAL, "SV_StartSound: volume = %f", volume);
    285 
    286 	if (attenuation < 0 || attenuation > 4)
    287 		Com_Error (ERR_FATAL, "SV_StartSound: attenuation = %f", attenuation);
    288 
    289 //	if (channel < 0 || channel > 15)
    290 //		Com_Error (ERR_FATAL, "SV_StartSound: channel = %i", channel);
    291 
    292 	if (timeofs < 0 || timeofs > 0.255)
    293 		Com_Error (ERR_FATAL, "SV_StartSound: timeofs = %f", timeofs);
    294 
    295 	ent = NUM_FOR_EDICT(entity);
    296 
    297 	if (channel & 8)	// no PHS flag
    298 	{
    299 		use_phs = false;
    300 		channel &= 7;
    301 	}
    302 	else
    303 		use_phs = true;
    304 
    305 	sendchan = (ent<<3) | (channel&7);
    306 
    307 	flags = 0;
    308 	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
    309 		flags |= SND_VOLUME;
    310 	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
    311 		flags |= SND_ATTENUATION;
    312 
    313 	// the client doesn't know that bmodels have weird origins
    314 	// the origin can also be explicitly set
    315 	if ( (entity->svflags & SVF_NOCLIENT)
    316 		|| (entity->solid == SOLID_BSP) 
    317 		|| origin )
    318 		flags |= SND_POS;
    319 
    320 	// always send the entity number for channel overrides
    321 	flags |= SND_ENT;
    322 
    323 	if (timeofs)
    324 		flags |= SND_OFFSET;
    325 
    326 	// use the entity origin unless it is a bmodel or explicitly specified
    327 	if (!origin)
    328 	{
    329 		origin = origin_v;
    330 		if (entity->solid == SOLID_BSP)
    331 		{
    332 			for (i=0 ; i<3 ; i++)
    333 				origin_v[i] = entity->s.origin[i]+0.5*(entity->mins[i]+entity->maxs[i]);
    334 		}
    335 		else
    336 		{
    337 			VectorCopy (entity->s.origin, origin_v);
    338 		}
    339 	}
    340 
    341 	MSG_WriteByte (&sv.multicast, svc_sound);
    342 	MSG_WriteByte (&sv.multicast, flags);
    343 	MSG_WriteByte (&sv.multicast, soundindex);
    344 
    345 	if (flags & SND_VOLUME)
    346 		MSG_WriteByte (&sv.multicast, volume*255);
    347 	if (flags & SND_ATTENUATION)
    348 		MSG_WriteByte (&sv.multicast, attenuation*64);
    349 	if (flags & SND_OFFSET)
    350 		MSG_WriteByte (&sv.multicast, timeofs*1000);
    351 
    352 	if (flags & SND_ENT)
    353 		MSG_WriteShort (&sv.multicast, sendchan);
    354 
    355 	if (flags & SND_POS)
    356 		MSG_WritePos (&sv.multicast, origin);
    357 
    358 	// if the sound doesn't attenuate,send it to everyone
    359 	// (global radio chatter, voiceovers, etc)
    360 	if (attenuation == ATTN_NONE)
    361 		use_phs = false;
    362 
    363 	if (channel & CHAN_RELIABLE)
    364 	{
    365 		if (use_phs)
    366 			SV_Multicast (origin, MULTICAST_PHS_R);
    367 		else
    368 			SV_Multicast (origin, MULTICAST_ALL_R);
    369 	}
    370 	else
    371 	{
    372 		if (use_phs)
    373 			SV_Multicast (origin, MULTICAST_PHS);
    374 		else
    375 			SV_Multicast (origin, MULTICAST_ALL);
    376 	}
    377 }           
    378 
    379 
    380 /*
    381 ===============================================================================
    382 
    383 FRAME UPDATES
    384 
    385 ===============================================================================
    386 */
    387 
    388 
    389 
    390 /*
    391 =======================
    392 SV_SendClientDatagram
    393 =======================
    394 */
    395 qboolean SV_SendClientDatagram (client_t *client)
    396 {
    397 	byte		msg_buf[MAX_MSGLEN];
    398 	sizebuf_t	msg;
    399 
    400 	SV_BuildClientFrame (client);
    401 
    402 	SZ_Init (&msg, msg_buf, sizeof(msg_buf));
    403 	msg.allowoverflow = true;
    404 
    405 	// send over all the relevant entity_state_t
    406 	// and the player_state_t
    407 	SV_WriteFrameToClient (client, &msg);
    408 
    409 	// copy the accumulated multicast datagram
    410 	// for this client out to the message
    411 	// it is necessary for this to be after the WriteEntities
    412 	// so that entity references will be current
    413 	if (client->datagram.overflowed)
    414 		Com_Printf ("WARNING: datagram overflowed for %s\n", client->name);
    415 	else
    416 		SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
    417 	SZ_Clear (&client->datagram);
    418 
    419 	if (msg.overflowed)
    420 	{	// must have room left for the packet header
    421 		Com_Printf ("WARNING: msg overflowed for %s\n", client->name);
    422 		SZ_Clear (&msg);
    423 	}
    424 
    425 	// send the datagram
    426 	Netchan_Transmit (&client->netchan, msg.cursize, msg.data);
    427 
    428 	// record the size for rate estimation
    429 	client->message_size[sv.framenum % RATE_MESSAGES] = msg.cursize;
    430 
    431 	return true;
    432 }
    433 
    434 
    435 /*
    436 ==================
    437 SV_DemoCompleted
    438 ==================
    439 */
    440 void SV_DemoCompleted (void)
    441 {
    442 	if (sv.demofile)
    443 	{
    444 		fclose (sv.demofile);
    445 		sv.demofile = NULL;
    446 	}
    447 	SV_Nextserver ();
    448 }
    449 
    450 
    451 /*
    452 =======================
    453 SV_RateDrop
    454 
    455 Returns true if the client is over its current
    456 bandwidth estimation and should not be sent another packet
    457 =======================
    458 */
    459 qboolean SV_RateDrop (client_t *c)
    460 {
    461 	int		total;
    462 	int		i;
    463 
    464 	// never drop over the loopback
    465 	if (c->netchan.remote_address.type == NA_LOOPBACK)
    466 		return false;
    467 
    468 	total = 0;
    469 
    470 	for (i = 0 ; i < RATE_MESSAGES ; i++)
    471 	{
    472 		total += c->message_size[i];
    473 	}
    474 
    475 	if (total > c->rate)
    476 	{
    477 		c->surpressCount++;
    478 		c->message_size[sv.framenum % RATE_MESSAGES] = 0;
    479 		return true;
    480 	}
    481 
    482 	return false;
    483 }
    484 
    485 /*
    486 =======================
    487 SV_SendClientMessages
    488 =======================
    489 */
    490 void SV_SendClientMessages (void)
    491 {
    492 	int			i;
    493 	client_t	*c;
    494 	int			msglen;
    495 	byte		msgbuf[MAX_MSGLEN];
    496 	int			r;
    497 
    498 	msglen = 0;
    499 
    500 	// read the next demo message if needed
    501 	if (sv.state == ss_demo && sv.demofile)
    502 	{
    503 		if (sv_paused->value)
    504 			msglen = 0;
    505 		else
    506 		{
    507 			// get the next message
    508 			r = fread (&msglen, 4, 1, sv.demofile);
    509 			if (r != 1)
    510 			{
    511 				SV_DemoCompleted ();
    512 				return;
    513 			}
    514 			msglen = LittleLong (msglen);
    515 			if (msglen == -1)
    516 			{
    517 				SV_DemoCompleted ();
    518 				return;
    519 			}
    520 			if (msglen > MAX_MSGLEN)
    521 				Com_Error (ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN");
    522 			r = fread (msgbuf, msglen, 1, sv.demofile);
    523 			if (r != 1)
    524 			{
    525 				SV_DemoCompleted ();
    526 				return;
    527 			}
    528 		}
    529 	}
    530 
    531 	// send a message to each connected client
    532 	for (i=0, c = svs.clients ; i<maxclients->value; i++, c++)
    533 	{
    534 		if (!c->state)
    535 			continue;
    536 		// if the reliable message overflowed,
    537 		// drop the client
    538 		if (c->netchan.message.overflowed)
    539 		{
    540 			SZ_Clear (&c->netchan.message);
    541 			SZ_Clear (&c->datagram);
    542 			SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
    543 			SV_DropClient (c);
    544 		}
    545 
    546 		if (sv.state == ss_cinematic 
    547 			|| sv.state == ss_demo 
    548 			|| sv.state == ss_pic
    549 			)
    550 			Netchan_Transmit (&c->netchan, msglen, msgbuf);
    551 		else if (c->state == cs_spawned)
    552 		{
    553 			// don't overrun bandwidth
    554 			if (SV_RateDrop (c))
    555 				continue;
    556 
    557 			SV_SendClientDatagram (c);
    558 		}
    559 		else
    560 		{
    561 	// just update reliable	if needed
    562 			if (c->netchan.message.cursize	|| curtime - c->netchan.last_sent > 1000 )
    563 				Netchan_Transmit (&c->netchan, 0, NULL);
    564 		}
    565 	}
    566 }
    567