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