File: server\sv_send.c

    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 
  568