home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / server / sv_send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  18.3 KB  |  807 lines

  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.