sv_send.c revision 9fd67c44777b350dc56f3e70c88963b0d966ffc7
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCopyright (C) 1996-1997 Id Software, Inc.
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThis program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20// sv_main.c -- server main program
21
22#include "qwsvdef.h"
23
24#define CHAN_AUTO   0
25#define CHAN_WEAPON 1
26#define CHAN_VOICE  2
27#define CHAN_ITEM   3
28#define CHAN_BODY   4
29
30/*
31=============================================================================
32
33Con_Printf redirection
34
35=============================================================================
36*/
37
38char	outputbuf[8000];
39
40redirect_t	sv_redirected;
41
42extern cvar_t sv_phs;
43
44/*
45==================
46SV_FlushRedirect
47==================
48*/
49void SV_FlushRedirect (void)
50{
51	char	send[8000+6];
52
53	if (sv_redirected == RD_PACKET)
54	{
55		send[0] = 0xff;
56		send[1] = 0xff;
57		send[2] = 0xff;
58		send[3] = 0xff;
59		send[4] = A2C_PRINT;
60		memcpy (send+5, outputbuf, strlen(outputbuf)+1);
61
62		NET_SendPacket (strlen(send)+1, send, net_from);
63	}
64	else if (sv_redirected == RD_CLIENT)
65	{
66		ClientReliableWrite_Begin (host_client, svc_print, strlen(outputbuf)+3);
67		ClientReliableWrite_Byte (host_client, PRINT_HIGH);
68		ClientReliableWrite_String (host_client, outputbuf);
69	}
70
71	// clear it
72	outputbuf[0] = 0;
73}
74
75
76/*
77==================
78SV_BeginRedirect
79
80  Send Con_Printf data to the remote client
81  instead of the console
82==================
83*/
84void SV_BeginRedirect (redirect_t rd)
85{
86	sv_redirected = rd;
87	outputbuf[0] = 0;
88}
89
90void SV_EndRedirect (void)
91{
92	SV_FlushRedirect ();
93	sv_redirected = RD_NONE;
94}
95
96
97/*
98================
99Con_Printf
100
101Handles cursor positioning, line wrapping, etc
102================
103*/
104#define	MAXPRINTMSG	4096
105// FIXME: make a buffer size safe vsprintf?
106void Con_Printf (char *fmt, ...)
107{
108	va_list		argptr;
109	char		msg[MAXPRINTMSG];
110
111	va_start (argptr,fmt);
112	vsprintf (msg,fmt,argptr);
113	va_end (argptr);
114
115	// add to redirected message
116	if (sv_redirected)
117	{
118		if (strlen (msg) + strlen(outputbuf) > sizeof(outputbuf) - 1)
119			SV_FlushRedirect ();
120		strcat (outputbuf, msg);
121		return;
122	}
123
124	Sys_Printf ("%s", msg);	// also echo to debugging console
125	if (sv_logfile)
126		fprintf (sv_logfile, "%s", msg);
127}
128
129/*
130================
131Con_DPrintf
132
133A Con_Printf that only shows up if the "developer" cvar is set
134================
135*/
136void Con_DPrintf (char *fmt, ...)
137{
138	va_list		argptr;
139	char		msg[MAXPRINTMSG];
140
141	if (!developer.value)
142		return;
143
144	va_start (argptr,fmt);
145	vsprintf (msg,fmt,argptr);
146	va_end (argptr);
147
148	Con_Printf ("%s", msg);
149}
150
151/*
152=============================================================================
153
154EVENT MESSAGES
155
156=============================================================================
157*/
158
159static void SV_PrintToClient(client_t *cl, int level, char *string)
160{
161	ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3);
162	ClientReliableWrite_Byte (cl, level);
163	ClientReliableWrite_String (cl, string);
164}
165
166
167/*
168=================
169SV_ClientPrintf
170
171Sends text across to be displayed if the level passes
172=================
173*/
174void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
175{
176	va_list		argptr;
177	char		string[1024];
178
179	if (level < cl->messagelevel)
180		return;
181
182	va_start (argptr,fmt);
183	vsprintf (string, fmt,argptr);
184	va_end (argptr);
185
186	SV_PrintToClient(cl, level, string);
187}
188
189/*
190=================
191SV_BroadcastPrintf
192
193Sends text to all active clients
194=================
195*/
196void SV_BroadcastPrintf (int level, char *fmt, ...)
197{
198	va_list		argptr;
199	char		string[1024];
200	client_t	*cl;
201	int			i;
202
203	va_start (argptr,fmt);
204	vsprintf (string, fmt,argptr);
205	va_end (argptr);
206
207	Sys_Printf ("%s", string);	// print to the console
208
209	for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
210	{
211		if (level < cl->messagelevel)
212			continue;
213		if (!cl->state)
214			continue;
215
216		SV_PrintToClient(cl, level, string);
217	}
218}
219
220/*
221=================
222SV_BroadcastCommand
223
224Sends text to all active clients
225=================
226*/
227void SV_BroadcastCommand (char *fmt, ...)
228{
229	va_list		argptr;
230	char		string[1024];
231
232	if (!sv.state)
233		return;
234	va_start (argptr,fmt);
235	vsprintf (string, fmt,argptr);
236	va_end (argptr);
237
238	MSG_WriteByte (&sv.reliable_datagram, svc_stufftext);
239	MSG_WriteString (&sv.reliable_datagram, string);
240}
241
242
243/*
244=================
245SV_Multicast
246
247Sends the contents of sv.multicast to a subset of the clients,
248then clears sv.multicast.
249
250MULTICAST_ALL	same as broadcast
251MULTICAST_PVS	send to clients potentially visible from org
252MULTICAST_PHS	send to clients potentially hearable from org
253=================
254*/
255void SV_Multicast (vec3_t origin, int to)
256{
257	client_t	*client;
258	byte		*mask;
259	mleaf_t		*leaf;
260	int			leafnum;
261	int			j;
262	qboolean	reliable;
263
264	leaf = Mod_PointInLeaf (origin, sv.worldmodel);
265	if (!leaf)
266		leafnum = 0;
267	else
268		leafnum = leaf - sv.worldmodel->leafs;
269
270	reliable = false;
271
272	switch (to)
273	{
274	case MULTICAST_ALL_R:
275		reliable = true;	// intentional fallthrough
276	case MULTICAST_ALL:
277		mask = sv.pvs;		// leaf 0 is everything;
278		break;
279
280	case MULTICAST_PHS_R:
281		reliable = true;	// intentional fallthrough
282	case MULTICAST_PHS:
283		mask = sv.phs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
284		break;
285
286	case MULTICAST_PVS_R:
287		reliable = true;	// intentional fallthrough
288	case MULTICAST_PVS:
289		mask = sv.pvs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
290		break;
291
292	default:
293		mask = NULL;
294		SV_Error ("SV_Multicast: bad to:%i", to);
295	}
296
297	// send the data to all relevent clients
298	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
299	{
300		if (client->state != cs_spawned)
301			continue;
302
303		if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) {
304			vec3_t delta;
305			VectorSubtract(origin, client->edict->v.origin, delta);
306			if (Length(delta) <= 1024)
307				goto inrange;
308		}
309
310		leaf = Mod_PointInLeaf (client->edict->v.origin, sv.worldmodel);
311		if (leaf)
312		{
313			// -1 is because pvs rows are 1 based, not 0 based like leafs
314			leafnum = leaf - sv.worldmodel->leafs - 1;
315			if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) )
316			{
317//				Con_Printf ("supressed multicast\n");
318				continue;
319			}
320		}
321
322inrange:
323		if (reliable) {
324			ClientReliableCheckBlock(client, sv.multicast.cursize);
325			ClientReliableWrite_SZ(client, sv.multicast.data, sv.multicast.cursize);
326		} else
327			SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
328	}
329
330	SZ_Clear (&sv.multicast);
331}
332
333
334/*
335==================
336SV_StartSound
337
338Each entity can have eight independant sound sources, like voice,
339weapon, feet, etc.
340
341Channel 0 is an auto-allocate channel, the others override anything
342allready running on that entity/channel pair.
343
344An attenuation of 0 will play full volume everywhere in the level.
345Larger attenuations will drop off.  (max 4 attenuation)
346
347==================
348*/
349void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
350    float attenuation)
351{
352    int         sound_num;
353    int			field_mask;
354    int			i;
355	int			ent;
356	vec3_t		origin;
357	qboolean	use_phs;
358	qboolean	reliable = false;
359
360	if (volume < 0 || volume > 255)
361		SV_Error ("SV_StartSound: volume = %i", volume);
362
363	if (attenuation < 0 || attenuation > 4)
364		SV_Error ("SV_StartSound: attenuation = %f", attenuation);
365
366	if (channel < 0 || channel > 15)
367		SV_Error ("SV_StartSound: channel = %i", channel);
368
369// find precache number for sound
370    for (sound_num=1 ; sound_num<MAX_SOUNDS
371        && sv.sound_precache[sound_num] ; sound_num++)
372        if (!strcmp(sample, sv.sound_precache[sound_num]))
373            break;
374
375    if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
376    {
377        Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
378        return;
379    }
380
381	ent = NUM_FOR_EDICT(entity);
382
383	if ((channel & 8) || !sv_phs.value)	// no PHS flag
384	{
385		if (channel & 8)
386			reliable = true; // sounds that break the phs are reliable
387		use_phs = false;
388		channel &= 7;
389	}
390	else
391		use_phs = true;
392
393//	if (channel == CHAN_BODY || channel == CHAN_VOICE)
394//		reliable = true;
395
396	channel = (ent<<3) | channel;
397
398	field_mask = 0;
399	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
400		channel |= SND_VOLUME;
401	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
402		channel |= SND_ATTENUATION;
403
404	// use the entity origin unless it is a bmodel
405	if (entity->v.solid == SOLID_BSP)
406	{
407		for (i=0 ; i<3 ; i++)
408			origin[i] = entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]);
409	}
410	else
411	{
412		VectorCopy (entity->v.origin, origin);
413	}
414
415	MSG_WriteByte (&sv.multicast, svc_sound);
416	MSG_WriteShort (&sv.multicast, channel);
417	if (channel & SND_VOLUME)
418		MSG_WriteByte (&sv.multicast, volume);
419	if (channel & SND_ATTENUATION)
420		MSG_WriteByte (&sv.multicast, attenuation*64);
421	MSG_WriteByte (&sv.multicast, sound_num);
422	for (i=0 ; i<3 ; i++)
423		MSG_WriteCoord (&sv.multicast, origin[i]);
424
425	if (use_phs)
426		SV_Multicast (origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS);
427	else
428		SV_Multicast (origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL);
429}
430
431
432/*
433===============================================================================
434
435FRAME UPDATES
436
437===============================================================================
438*/
439
440int		sv_nailmodel, sv_supernailmodel, sv_playermodel;
441
442void SV_FindModelNumbers (void)
443{
444	int		i;
445
446	sv_nailmodel = -1;
447	sv_supernailmodel = -1;
448	sv_playermodel = -1;
449
450	for (i=0 ; i<MAX_MODELS ; i++)
451	{
452		if (!sv.model_precache[i])
453			break;
454		if (!strcmp(sv.model_precache[i],"progs/spike.mdl"))
455			sv_nailmodel = i;
456		if (!strcmp(sv.model_precache[i],"progs/s_spike.mdl"))
457			sv_supernailmodel = i;
458		if (!strcmp(sv.model_precache[i],"progs/player.mdl"))
459			sv_playermodel = i;
460	}
461}
462
463
464/*
465==================
466SV_WriteClientdataToMessage
467
468==================
469*/
470void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
471{
472	int		i;
473	edict_t	*other;
474	edict_t	*ent;
475
476	ent = client->edict;
477
478	// send the chokecount for r_netgraph
479	if (client->chokecount)
480	{
481		MSG_WriteByte (msg, svc_chokecount);
482		MSG_WriteByte (msg, client->chokecount);
483		client->chokecount = 0;
484	}
485
486	// send a damage message if the player got hit this frame
487	if (ent->v.dmg_take || ent->v.dmg_save)
488	{
489		other = PROG_TO_EDICT(ent->v.dmg_inflictor);
490		MSG_WriteByte (msg, svc_damage);
491		MSG_WriteByte (msg, ent->v.dmg_save);
492		MSG_WriteByte (msg, ent->v.dmg_take);
493		for (i=0 ; i<3 ; i++)
494			MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
495
496		ent->v.dmg_take = 0;
497		ent->v.dmg_save = 0;
498	}
499
500	// a fixangle might get lost in a dropped packet.  Oh well.
501	if ( ent->v.fixangle )
502	{
503		MSG_WriteByte (msg, svc_setangle);
504		for (i=0 ; i < 3 ; i++)
505			MSG_WriteAngle (msg, ent->v.angles[i] );
506		ent->v.fixangle = 0;
507	}
508}
509
510/*
511=======================
512SV_UpdateClientStats
513
514Performs a delta update of the stats array.  This should only be performed
515when a reliable message can be delivered this frame.
516=======================
517*/
518void SV_UpdateClientStats (client_t *client)
519{
520	edict_t	*ent;
521	int		stats[MAX_CL_STATS];
522	int		i;
523
524	ent = client->edict;
525	memset (stats, 0, sizeof(stats));
526
527	// if we are a spectator and we are tracking a player, we get his stats
528	// so our status bar reflects his
529	if (client->spectator && client->spec_track > 0)
530		ent = svs.clients[client->spec_track - 1].edict;
531
532	stats[STAT_HEALTH] = ent->v.health;
533	stats[STAT_WEAPON] = SV_ModelIndex(PR_GetString(ent->v.weaponmodel));
534	stats[STAT_AMMO] = ent->v.currentammo;
535	stats[STAT_ARMOR] = ent->v.armorvalue;
536	stats[STAT_SHELLS] = ent->v.ammo_shells;
537	stats[STAT_NAILS] = ent->v.ammo_nails;
538	stats[STAT_ROCKETS] = ent->v.ammo_rockets;
539	stats[STAT_CELLS] = ent->v.ammo_cells;
540	if (!client->spectator)
541		stats[STAT_ACTIVEWEAPON] = ent->v.weapon;
542	// stuff the sigil bits into the high bits of items for sbar
543	stats[STAT_ITEMS] = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
544
545	for (i=0 ; i<MAX_CL_STATS ; i++)
546		if (stats[i] != client->stats[i])
547		{
548			client->stats[i] = stats[i];
549			if (stats[i] >=0 && stats[i] <= 255)
550			{
551				ClientReliableWrite_Begin(client, svc_updatestat, 3);
552				ClientReliableWrite_Byte(client, i);
553				ClientReliableWrite_Byte(client, stats[i]);
554			}
555			else
556			{
557				ClientReliableWrite_Begin(client, svc_updatestatlong, 6);
558				ClientReliableWrite_Byte(client, i);
559				ClientReliableWrite_Long(client, stats[i]);
560			}
561		}
562}
563
564/*
565=======================
566SV_SendClientDatagram
567=======================
568*/
569qboolean SV_SendClientDatagram (client_t *client)
570{
571	byte		buf[MAX_DATAGRAM];
572	sizebuf_t	msg;
573
574	msg.data = buf;
575	msg.maxsize = sizeof(buf);
576	msg.cursize = 0;
577	msg.allowoverflow = true;
578	msg.overflowed = false;
579
580	// add the client specific data to the datagram
581	SV_WriteClientdataToMessage (client, &msg);
582
583	// send over all the objects that are in the PVS
584	// this will include clients, a packetentities, and
585	// possibly a nails update
586	SV_WriteEntitiesToClient (client, &msg);
587
588	// copy the accumulated multicast datagram
589	// for this client out to the message
590	if (client->datagram.overflowed)
591		Con_Printf ("WARNING: datagram overflowed for %s\n", client->name);
592	else
593		SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
594	SZ_Clear (&client->datagram);
595
596	// send deltas over reliable stream
597	if (Netchan_CanReliable (&client->netchan))
598		SV_UpdateClientStats (client);
599
600	if (msg.overflowed)
601	{
602		Con_Printf ("WARNING: msg overflowed for %s\n", client->name);
603		SZ_Clear (&msg);
604	}
605
606	// send the datagram
607	Netchan_Transmit (&client->netchan, msg.cursize, buf);
608
609	return true;
610}
611
612/*
613=======================
614SV_UpdateToReliableMessages
615=======================
616*/
617void SV_UpdateToReliableMessages (void)
618{
619	int			i, j;
620	client_t *client;
621	eval_t *val;
622	edict_t *ent;
623
624// check for changes to be sent over the reliable streams to all clients
625	for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
626	{
627		if (host_client->state != cs_spawned)
628			continue;
629		if (host_client->sendinfo)
630		{
631			host_client->sendinfo = false;
632			SV_FullClientUpdate (host_client, &sv.reliable_datagram);
633		}
634		if (host_client->old_frags != host_client->edict->v.frags)
635		{
636			for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
637			{
638				if (client->state < cs_connected)
639					continue;
640				ClientReliableWrite_Begin(client, svc_updatefrags, 4);
641				ClientReliableWrite_Byte(client, i);
642				ClientReliableWrite_Short(client, host_client->edict->v.frags);
643			}
644
645			host_client->old_frags = host_client->edict->v.frags;
646		}
647
648		// maxspeed/entgravity changes
649		ent = host_client->edict;
650
651		val = GetEdictFieldValue(ent, "gravity");
652		if (val && host_client->entgravity != val->_float) {
653			host_client->entgravity = val->_float;
654			ClientReliableWrite_Begin(host_client, svc_entgravity, 5);
655			ClientReliableWrite_Float(host_client, host_client->entgravity);
656		}
657		val = GetEdictFieldValue(ent, "maxspeed");
658		if (val && host_client->maxspeed != val->_float) {
659			host_client->maxspeed = val->_float;
660			ClientReliableWrite_Begin(host_client, svc_maxspeed, 5);
661			ClientReliableWrite_Float(host_client, host_client->maxspeed);
662		}
663
664	}
665
666	if (sv.datagram.overflowed)
667		SZ_Clear (&sv.datagram);
668
669	// append the broadcast messages to each client messages
670	for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
671	{
672		if (client->state < cs_connected)
673			continue;	// reliables go to all connected or spawned
674
675		ClientReliableCheckBlock(client, sv.reliable_datagram.cursize);
676		ClientReliableWrite_SZ(client, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
677
678		if (client->state != cs_spawned)
679			continue;	// datagrams only go to spawned
680		SZ_Write (&client->datagram
681			, sv.datagram.data
682			, sv.datagram.cursize);
683	}
684
685	SZ_Clear (&sv.reliable_datagram);
686	SZ_Clear (&sv.datagram);
687}
688
689#ifdef _WIN32
690#pragma optimize( "", off )
691#endif
692
693
694
695/*
696=======================
697SV_SendClientMessages
698=======================
699*/
700void SV_SendClientMessages (void)
701{
702	int			i, j;
703	client_t	*c;
704
705// update frags, names, etc
706	SV_UpdateToReliableMessages ();
707
708// build individual updates
709	for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
710	{
711		if (!c->state)
712			continue;
713
714		if (c->drop) {
715			SV_DropClient(c);
716			c->drop = false;
717			continue;
718		}
719
720		// check to see if we have a backbuf to stick in the reliable
721		if (c->num_backbuf) {
722			// will it fit?
723			if (c->netchan.message.cursize + c->backbuf_size[0] <
724				c->netchan.message.maxsize) {
725
726				Con_DPrintf("%s: backbuf %d bytes\n",
727					c->name, c->backbuf_size[0]);
728
729				// it'll fit
730				SZ_Write(&c->netchan.message, c->backbuf_data[0],
731					c->backbuf_size[0]);
732
733				//move along, move along
734				for (j = 1; j < c->num_backbuf; j++) {
735					memcpy(c->backbuf_data[j - 1], c->backbuf_data[j],
736						c->backbuf_size[j]);
737					c->backbuf_size[j - 1] = c->backbuf_size[j];
738				}
739
740				c->num_backbuf--;
741				if (c->num_backbuf) {
742					memset(&c->backbuf, 0, sizeof(c->backbuf));
743					c->backbuf.data = c->backbuf_data[c->num_backbuf - 1];
744					c->backbuf.cursize = c->backbuf_size[c->num_backbuf - 1];
745					c->backbuf.maxsize = sizeof(c->backbuf_data[c->num_backbuf - 1]);
746				}
747			}
748		}
749
750		// if the reliable message overflowed,
751		// drop the client
752		if (c->netchan.message.overflowed)
753		{
754			SZ_Clear (&c->netchan.message);
755			SZ_Clear (&c->datagram);
756			SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
757			Con_Printf ("WARNING: reliable overflow for %s\n",c->name);
758			SV_DropClient (c);
759			c->send_message = true;
760			c->netchan.cleartime = 0;	// don't choke this message
761		}
762
763		// only send messages if the client has sent one
764		// and the bandwidth is not choked
765		if (!c->send_message)
766			continue;
767		c->send_message = false;	// try putting this after choke?
768		if (!sv.paused && !Netchan_CanPacket (&c->netchan))
769		{
770			c->chokecount++;
771			continue;		// bandwidth choke
772		}
773
774		if (c->state == cs_spawned)
775			SV_SendClientDatagram (c);
776		else
777			Netchan_Transmit (&c->netchan, 0, NULL);	// just update reliable
778
779	}
780}
781
782#ifdef _WIN32
783#pragma optimize( "", on )
784#endif
785
786
787
788/*
789=======================
790SV_SendMessagesToAll
791
792FIXME: does this sequence right?
793=======================
794*/
795void SV_SendMessagesToAll (void)
796{
797	int			i;
798	client_t	*c;
799
800	for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
801		if (c->state)		// FIXME: should this only send to active?
802			c->send_message = true;
803
804	SV_SendClientMessages ();
805}
806
807