1 /* 2 Copyright (C) 1996-1997 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 "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 33 Con_Printf redirection 34 35 ============================================================================= 36 */ 37 38 char outputbuf[8000]; 39 40 redirect_t sv_redirected; 41 42 extern cvar_t sv_phs; 43 44 /* 45 ================== 46 SV_FlushRedirect 47 ================== 48 */ 49 void 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 ================== 78 SV_BeginRedirect 79 80 Send Con_Printf data to the remote client 81 instead of the console 82 ================== 83 */ 84 void SV_BeginRedirect (redirect_t rd) 85 { 86 sv_redirected = rd; 87 outputbuf[0] = 0; 88 } 89 90 void SV_EndRedirect (void) 91 { 92 SV_FlushRedirect (); 93 sv_redirected = RD_NONE; 94 } 95 96 97 /* 98 ================ 99 Con_Printf 100 101 Handles cursor positioning, line wrapping, etc 102 ================ 103 */ 104 #define MAXPRINTMSG 4096 105 // FIXME: make a buffer size safe vsprintf? 106 void 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 ================ 131 Con_DPrintf 132 133 A Con_Printf that only shows up if the "developer" cvar is set 134 ================ 135 */ 136 void 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 154 EVENT MESSAGES 155 156 ============================================================================= 157 */ 158 159 static 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 ================= 169 SV_ClientPrintf 170 171 Sends text across to be displayed if the level passes 172 ================= 173 */ 174 void 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 ================= 191 SV_BroadcastPrintf 192 193 Sends text to all active clients 194 ================= 195 */ 196 void 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 ================= 222 SV_BroadcastCommand 223 224 Sends text to all active clients 225 ================= 226 */ 227 void 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 ================= 245 SV_Multicast 246 247 Sends the contents of sv.multicast to a subset of the clients, 248 then clears sv.multicast. 249 250 MULTICAST_ALL same as broadcast 251 MULTICAST_PVS send to clients potentially visible from org 252 MULTICAST_PHS send to clients potentially hearable from org 253 ================= 254 */ 255 void 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 322 inrange: 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 ================== 336 SV_StartSound 337 338 Each entity can have eight independant sound sources, like voice, 339 weapon, feet, etc. 340 341 Channel 0 is an auto-allocate channel, the others override anything 342 allready running on that entity/channel pair. 343 344 An attenuation of 0 will play full volume everywhere in the level. 345 Larger attenuations will drop off. (max 4 attenuation) 346 347 ================== 348 */ 349 void 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 435 FRAME UPDATES 436 437 =============================================================================== 438 */ 439 440 int sv_nailmodel, sv_supernailmodel, sv_playermodel; 441 442 void 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 ================== 466 SV_WriteClientdataToMessage 467 468 ================== 469 */ 470 void 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 ======================= 512 SV_UpdateClientStats 513 514 Performs a delta update of the stats array. This should only be performed 515 when a reliable message can be delivered this frame. 516 ======================= 517 */ 518 void 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 ======================= 566 SV_SendClientDatagram 567 ======================= 568 */ 569 qboolean 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 ======================= 614 SV_UpdateToReliableMessages 615 ======================= 616 */ 617 void 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 ======================= 697 SV_SendClientMessages 698 ======================= 699 */ 700 void 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 ======================= 790 SV_SendMessagesToAll 791 792 FIXME: does this sequence right? 793 ======================= 794 */ 795 void 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