home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / cl_parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  29.1 KB  |  1,384 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. // cl_parse.c  -- parse a message received from the server
  21.  
  22. #include "quakedef.h"
  23.  
  24. char *svc_strings[] =
  25. {
  26.     "svc_bad",
  27.     "svc_nop",
  28.     "svc_disconnect",
  29.     "svc_updatestat",
  30.     "svc_version",        // [long] server version
  31.     "svc_setview",        // [short] entity number
  32.     "svc_sound",            // <see code>
  33.     "svc_time",            // [float] server time
  34.     "svc_print",            // [string] null terminated string
  35.     "svc_stufftext",        // [string] stuffed into client's console buffer
  36.                         // the string should be \n terminated
  37.     "svc_setangle",        // [vec3] set the view angle to this absolute value
  38.     
  39.     "svc_serverdata",        // [long] version ...
  40.     "svc_lightstyle",        // [byte] [string]
  41.     "svc_updatename",        // [byte] [string]
  42.     "svc_updatefrags",    // [byte] [short]
  43.     "svc_clientdata",        // <shortbits + data>
  44.     "svc_stopsound",        // <see code>
  45.     "svc_updatecolors",    // [byte] [byte]
  46.     "svc_particle",        // [vec3] <variable>
  47.     "svc_damage",            // [byte] impact [byte] blood [vec3] from
  48.     
  49.     "svc_spawnstatic",
  50.     "OBSOLETE svc_spawnbinary",
  51.     "svc_spawnbaseline",
  52.     
  53.     "svc_temp_entity",        // <variable>
  54.     "svc_setpause",
  55.     "svc_signonnum",
  56.     "svc_centerprint",
  57.     "svc_killedmonster",
  58.     "svc_foundsecret",
  59.     "svc_spawnstaticsound",
  60.     "svc_intermission",
  61.     "svc_finale",
  62.  
  63.     "svc_cdtrack",
  64.     "svc_sellscreen",
  65.  
  66.     "svc_smallkick",
  67.     "svc_bigkick",
  68.  
  69.     "svc_updateping",
  70.     "svc_updateentertime",
  71.  
  72.     "svc_updatestatlong",
  73.     "svc_muzzleflash",
  74.     "svc_updateuserinfo",
  75.     "svc_download",
  76.     "svc_playerinfo",
  77.     "svc_nails",
  78.     "svc_choke",
  79.     "svc_modellist",
  80.     "svc_soundlist",
  81.     "svc_packetentities",
  82.      "svc_deltapacketentities",
  83.     "svc_maxspeed",
  84.     "svc_entgravity",
  85.  
  86.     "svc_setinfo",
  87.     "svc_serverinfo",
  88.     "svc_updatepl",
  89.     "NEW PROTOCOL",
  90.     "NEW PROTOCOL",
  91.     "NEW PROTOCOL",
  92.     "NEW PROTOCOL",
  93.     "NEW PROTOCOL",
  94.     "NEW PROTOCOL",
  95.     "NEW PROTOCOL",
  96.     "NEW PROTOCOL",
  97.     "NEW PROTOCOL",
  98.     "NEW PROTOCOL",
  99.     "NEW PROTOCOL",
  100.     "NEW PROTOCOL",
  101.     "NEW PROTOCOL"
  102. };
  103.  
  104. int    oldparsecountmod;
  105. int    parsecountmod;
  106. double    parsecounttime;
  107.  
  108. int        cl_spikeindex, cl_playerindex, cl_flagindex;
  109.  
  110. //=============================================================================
  111.  
  112. int packet_latency[NET_TIMINGS];
  113.  
  114. int CL_CalcNet (void)
  115. {
  116.     int        a, i;
  117.     frame_t    *frame;
  118.     int lost;
  119.     char st[80];
  120.  
  121.     for (i=cls.netchan.outgoing_sequence-UPDATE_BACKUP+1
  122.         ; i <= cls.netchan.outgoing_sequence
  123.         ; i++)
  124.     {
  125.         frame = &cl.frames[i&UPDATE_MASK];
  126.         if (frame->receivedtime == -1)
  127.             packet_latency[i&NET_TIMINGSMASK] = 9999;    // dropped
  128.         else if (frame->receivedtime == -2)
  129.             packet_latency[i&NET_TIMINGSMASK] = 10000;    // choked
  130.         else if (frame->invalid)
  131.             packet_latency[i&NET_TIMINGSMASK] = 9998;    // invalid delta
  132.         else
  133.             packet_latency[i&NET_TIMINGSMASK] = (frame->receivedtime - frame->senttime)*20;
  134.     }
  135.  
  136.     lost = 0;
  137.     for (a=0 ; a<NET_TIMINGS ; a++)
  138.     {
  139.         i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
  140.         if (packet_latency[i] == 9999)
  141.             lost++;
  142.     }
  143.     return lost * 100 / NET_TIMINGS;
  144. }
  145.  
  146. //=============================================================================
  147.  
  148. /*
  149. ===============
  150. CL_CheckOrDownloadFile
  151.  
  152. Returns true if the file exists, otherwise it attempts
  153. to start a download from the server.
  154. ===============
  155. */
  156. qboolean    CL_CheckOrDownloadFile (char *filename)
  157. {
  158.     FILE    *f;
  159.  
  160.     if (strstr (filename, ".."))
  161.     {
  162.         Con_Printf ("Refusing to download a path with ..\n");
  163.         return true;
  164.     }
  165.  
  166.     COM_FOpenFile (filename, &f);
  167.     if (f)
  168.     {    // it exists, no need to download
  169.         fclose (f);
  170.         return true;
  171.     }
  172.  
  173.     //ZOID - can't download when recording
  174.     if (cls.demorecording) {
  175.         Con_Printf("Unable to download %s in record mode.\n", cls.downloadname);
  176.         return true;
  177.     }
  178.     //ZOID - can't download when playback
  179.     if (cls.demoplayback)
  180.         return true;
  181.  
  182.     strcpy (cls.downloadname, filename);
  183.     Con_Printf ("Downloading %s...\n", cls.downloadname);
  184.  
  185.     // download to a temp name, and only rename
  186.     // to the real name when done, so if interrupted
  187.     // a runt file wont be left
  188.     COM_StripExtension (cls.downloadname, cls.downloadtempname);
  189.     strcat (cls.downloadtempname, ".tmp");
  190.  
  191.     MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  192.     MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname));
  193.  
  194.     cls.downloadnumber++;
  195.  
  196.     return false;
  197. }
  198.  
  199. /*
  200. =================
  201. Model_NextDownload
  202. =================
  203. */
  204. void Model_NextDownload (void)
  205. {
  206.     char    *s;
  207.     int        i;
  208.     extern    char gamedirfile[];
  209.  
  210.     if (cls.downloadnumber == 0)
  211.     {
  212.         Con_Printf ("Checking models...\n");
  213.         cls.downloadnumber = 1;
  214.     }
  215.  
  216.     cls.downloadtype = dl_model;
  217.     for ( 
  218.         ; cl.model_name[cls.downloadnumber][0]
  219.         ; cls.downloadnumber++)
  220.     {
  221.         s = cl.model_name[cls.downloadnumber];
  222.         if (s[0] == '*')
  223.             continue;    // inline brush model
  224.         if (!CL_CheckOrDownloadFile(s))
  225.             return;        // started a download
  226.     }
  227.  
  228.     for (i=1 ; i<MAX_MODELS ; i++)
  229.     {
  230.         if (!cl.model_name[i][0])
  231.             break;
  232.  
  233.         cl.model_precache[i] = Mod_ForName (cl.model_name[i], false);
  234.  
  235.         if (!cl.model_precache[i])
  236.         {
  237.             Con_Printf ("\nThe required model file '%s' could not be found or downloaded.\n\n"
  238.                 , cl.model_name[i]);
  239.             Con_Printf ("You may need to download or purchase a %s client "
  240.                 "pack in order to play on this server.\n\n", gamedirfile);
  241.             CL_Disconnect ();
  242.             return;
  243.         }
  244.     }
  245.  
  246.     // all done
  247.     cl.worldmodel = cl.model_precache[1];    
  248.     R_NewMap ();
  249.     Hunk_Check ();        // make sure nothing is hurt
  250.  
  251.     // done with modellist, request first of static signon messages
  252.     MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  253. //    MSG_WriteString (&cls.netchan.message, va("prespawn %i 0 %i", cl.servercount, cl.worldmodel->checksum2));
  254.     MSG_WriteString (&cls.netchan.message, va(prespawn_name, cl.servercount, cl.worldmodel->checksum2));
  255. }
  256.  
  257. /*
  258. =================
  259. Sound_NextDownload
  260. =================
  261. */
  262. void Sound_NextDownload (void)
  263. {
  264.     char    *s;
  265.     int        i;
  266.  
  267.     if (cls.downloadnumber == 0)
  268.     {
  269.         Con_Printf ("Checking sounds...\n");
  270.         cls.downloadnumber = 1;
  271.     }
  272.  
  273.     cls.downloadtype = dl_sound;
  274.     for ( 
  275.         ; cl.sound_name[cls.downloadnumber][0]
  276.         ; cls.downloadnumber++)
  277.     {
  278.         s = cl.sound_name[cls.downloadnumber];
  279.         if (!CL_CheckOrDownloadFile(va("sound/%s",s)))
  280.             return;        // started a download
  281.     }
  282.  
  283.     for (i=1 ; i<MAX_SOUNDS ; i++)
  284.     {
  285.         if (!cl.sound_name[i][0])
  286.             break;
  287.         cl.sound_precache[i] = S_PrecacheSound (cl.sound_name[i]);
  288.     }
  289.  
  290.     // done with sounds, request models now
  291.     memset (cl.model_precache, 0, sizeof(cl.model_precache));
  292.     cl_playerindex = -1;
  293.     cl_spikeindex = -1;
  294.     cl_flagindex = -1;
  295.     MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  296. //    MSG_WriteString (&cls.netchan.message, va("modellist %i 0", cl.servercount));
  297.     MSG_WriteString (&cls.netchan.message, va(modellist_name, cl.servercount, 0));
  298. }
  299.  
  300.  
  301. /*
  302. ======================
  303. CL_RequestNextDownload
  304. ======================
  305. */
  306. void CL_RequestNextDownload (void)
  307. {
  308.     switch (cls.downloadtype)
  309.     {
  310.     case dl_single:
  311.         break;
  312.     case dl_skin:
  313.         Skin_NextDownload ();
  314.         break;
  315.     case dl_model:
  316.         Model_NextDownload ();
  317.         break;
  318.     case dl_sound:
  319.         Sound_NextDownload ();
  320.         break;
  321.     case dl_none:
  322.     default:
  323.         Con_DPrintf("Unknown download type.\n");
  324.     }
  325. }
  326.  
  327. /*
  328. =====================
  329. CL_ParseDownload
  330.  
  331. A download message has been received from the server
  332. =====================
  333. */
  334. void CL_ParseDownload (void)
  335. {
  336.     int        size, percent;
  337.     byte    name[1024];
  338.     int        r;
  339.  
  340.  
  341.     // read the data
  342.     size = MSG_ReadShort ();
  343.     percent = MSG_ReadByte ();
  344.  
  345.     if (cls.demoplayback) {
  346.         if (size > 0)
  347.             msg_readcount += size;
  348.         return; // not in demo playback
  349.     }
  350.  
  351.     if (size == -1)
  352.     {
  353.         Con_Printf ("File not found.\n");
  354.         if (cls.download)
  355.         {
  356.             Con_Printf ("cls.download shouldn't have been set\n");
  357.             fclose (cls.download);
  358.             cls.download = NULL;
  359.         }
  360.         CL_RequestNextDownload ();
  361.         return;
  362.     }
  363.  
  364.     // open the file if not opened yet
  365.     if (!cls.download)
  366.     {
  367.         if (strncmp(cls.downloadtempname,"skins/",6))
  368.             sprintf (name, "%s/%s", com_gamedir, cls.downloadtempname);
  369.         else
  370.             sprintf (name, "qw/%s", cls.downloadtempname);
  371.  
  372.         COM_CreatePath (name);
  373.  
  374.         cls.download = fopen (name, "wb");
  375.         if (!cls.download)
  376.         {
  377.             msg_readcount += size;
  378.             Con_Printf ("Failed to open %s\n", cls.downloadtempname);
  379.             CL_RequestNextDownload ();
  380.             return;
  381.         }
  382.     }
  383.  
  384.     fwrite (net_message.data + msg_readcount, 1, size, cls.download);
  385.     msg_readcount += size;
  386.  
  387.     if (percent != 100)
  388.     {
  389. // change display routines by zoid
  390.         // request next block
  391. #if 0
  392.         Con_Printf (".");
  393.         if (10*(percent/10) != cls.downloadpercent)
  394.         {
  395.             cls.downloadpercent = 10*(percent/10);
  396.             Con_Printf ("%i%%", cls.downloadpercent);
  397.         }
  398. #endif
  399.         cls.downloadpercent = percent;
  400.  
  401.         MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  402.         SZ_Print (&cls.netchan.message, "nextdl");
  403.     }
  404.     else
  405.     {
  406.         char    oldn[MAX_OSPATH];
  407.         char    newn[MAX_OSPATH];
  408.  
  409. #if 0
  410.         Con_Printf ("100%%\n");
  411. #endif
  412.  
  413.         fclose (cls.download);
  414.  
  415.         // rename the temp file to it's final name
  416.         if (strcmp(cls.downloadtempname, cls.downloadname)) {
  417.             if (strncmp(cls.downloadtempname,"skins/",6)) {
  418.                 sprintf (oldn, "%s/%s", com_gamedir, cls.downloadtempname);
  419.                 sprintf (newn, "%s/%s", com_gamedir, cls.downloadname);
  420.             } else {
  421.                 sprintf (oldn, "qw/%s", cls.downloadtempname);
  422.                 sprintf (newn, "qw/%s", cls.downloadname);
  423.             }
  424.             r = rename (oldn, newn);
  425.             if (r)
  426.                 Con_Printf ("failed to rename.\n");
  427.         }
  428.  
  429.         cls.download = NULL;
  430.         cls.downloadpercent = 0;
  431.  
  432.         // get another file if needed
  433.  
  434.         CL_RequestNextDownload ();
  435.     }
  436. }
  437.  
  438. static byte *upload_data;
  439. static int upload_pos;
  440. static int upload_size;
  441.  
  442. void CL_NextUpload(void)
  443. {
  444.     byte    buffer[1024];
  445.     int        r;
  446.     int        percent;
  447.     int        size;
  448.  
  449.     if (!upload_data)
  450.         return;
  451.  
  452.     r = upload_size - upload_pos;
  453.     if (r > 768)
  454.         r = 768;
  455.     memcpy(buffer, upload_data + upload_pos, r);
  456.     MSG_WriteByte (&cls.netchan.message, clc_upload);
  457.     MSG_WriteShort (&cls.netchan.message, r);
  458.  
  459.     upload_pos += r;
  460.     size = upload_size;
  461.     if (!size)
  462.         size = 1;
  463.     percent = upload_pos*100/size;
  464.     MSG_WriteByte (&cls.netchan.message, percent);
  465.     SZ_Write (&cls.netchan.message, buffer, r);
  466.  
  467. Con_DPrintf ("UPLOAD: %6d: %d written\n", upload_pos - r, r);
  468.  
  469.     if (upload_pos != upload_size)
  470.         return;
  471.  
  472.     Con_Printf ("Upload completed\n");
  473.  
  474.     free(upload_data);
  475.     upload_data = 0;
  476.     upload_pos = upload_size = 0;
  477. }
  478.  
  479. void CL_StartUpload (byte *data, int size)
  480. {
  481.     if (cls.state < ca_onserver)
  482.         return; // gotta be connected
  483.  
  484.     // override
  485.     if (upload_data)
  486.         free(upload_data);
  487.  
  488. Con_DPrintf("Upload starting of %d...\n", size);
  489.  
  490.     upload_data = malloc(size);
  491.     memcpy(upload_data, data, size);
  492.     upload_size = size;
  493.     upload_pos = 0;
  494.  
  495.     CL_NextUpload();
  496.  
  497. qboolean CL_IsUploading(void)
  498. {
  499.     if (upload_data)
  500.         return true;
  501.     return false;
  502. }
  503.  
  504. void CL_StopUpload(void)
  505. {
  506.     if (upload_data)
  507.         free(upload_data);
  508.     upload_data = NULL;
  509. }
  510.  
  511. /*
  512. =====================================================================
  513.  
  514.   SERVER CONNECTING MESSAGES
  515.  
  516. =====================================================================
  517. */
  518.  
  519. /*
  520. ==================
  521. CL_ParseServerData
  522. ==================
  523. */
  524. void CL_ParseServerData (void)
  525. {
  526.     char    *str;
  527.     FILE    *f;
  528.     char    fn[MAX_OSPATH];
  529.     qboolean    cflag = false;
  530.     extern    char    gamedirfile[MAX_OSPATH];
  531.     int protover;
  532.     
  533.     Con_DPrintf ("Serverdata packet received.\n");
  534. //
  535. // wipe the client_state_t struct
  536. //
  537.     CL_ClearState ();
  538.  
  539. // parse protocol version number
  540. // allow 2.2 and 2.29 demos to play
  541.     protover = MSG_ReadLong ();
  542.     if (protover != PROTOCOL_VERSION && 
  543.         !(cls.demoplayback && (protover == 26 || protover == 27 || protover == 28)))
  544.         Host_EndGame ("Server returned version %i, not %i\nYou probably need to upgrade.\nCheck http://www.quakeworld.net/", protover, PROTOCOL_VERSION);
  545.  
  546.     cl.servercount = MSG_ReadLong ();
  547.  
  548.     // game directory
  549.     str = MSG_ReadString ();
  550.  
  551.     if (stricmp(gamedirfile, str)) {
  552.         // save current config
  553.         Host_WriteConfiguration (); 
  554.         cflag = true;
  555.     }
  556.  
  557.     COM_Gamedir(str);
  558.  
  559.     //ZOID--run the autoexec.cfg in the gamedir
  560.     //if it exists
  561.     if (cflag) {
  562.         sprintf(fn, "%s/%s", com_gamedir, "config.cfg");
  563.         if ((f = fopen(fn, "r")) != NULL) {
  564.             fclose(f);
  565.             Cbuf_AddText ("cl_warncmd 0\n");
  566.             Cbuf_AddText("exec config.cfg\n");
  567.             Cbuf_AddText("exec frontend.cfg\n");
  568.             Cbuf_AddText ("cl_warncmd 1\n");
  569.         }
  570.     }
  571.  
  572.     // parse player slot, high bit means spectator
  573.     cl.playernum = MSG_ReadByte ();
  574.     if (cl.playernum & 128)
  575.     {
  576.         cl.spectator = true;
  577.         cl.playernum &= ~128;
  578.     }
  579.  
  580.     // get the full level name
  581.     str = MSG_ReadString ();
  582.     strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
  583.  
  584.     // get the movevars
  585.     movevars.gravity            = MSG_ReadFloat();
  586.     movevars.stopspeed          = MSG_ReadFloat();
  587.     movevars.maxspeed           = MSG_ReadFloat();
  588.     movevars.spectatormaxspeed  = MSG_ReadFloat();
  589.     movevars.accelerate         = MSG_ReadFloat();
  590.     movevars.airaccelerate      = MSG_ReadFloat();
  591.     movevars.wateraccelerate    = MSG_ReadFloat();
  592.     movevars.friction           = MSG_ReadFloat();
  593.     movevars.waterfriction      = MSG_ReadFloat();
  594.     movevars.entgravity         = MSG_ReadFloat();
  595.  
  596.     // seperate the printfs so the server message can have a color
  597.     Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
  598.     Con_Printf ("%c%s\n", 2, str);
  599.  
  600.     // ask for the sound list next
  601.     memset(cl.sound_name, 0, sizeof(cl.sound_name));
  602.     MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  603. //    MSG_WriteString (&cls.netchan.message, va("soundlist %i 0", cl.servercount));
  604.     MSG_WriteString (&cls.netchan.message, va(soundlist_name, cl.servercount, 0));
  605.  
  606.     // now waiting for downloads, etc
  607.     cls.state = ca_onserver;
  608. }
  609.  
  610. /*
  611. ==================
  612. CL_ParseSoundlist
  613. ==================
  614. */
  615. void CL_ParseSoundlist (void)
  616. {
  617.     int    numsounds;
  618.     char    *str;
  619.     int n;
  620.  
  621. // precache sounds
  622. //    memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
  623.  
  624.     numsounds = MSG_ReadByte();
  625.  
  626.     for (;;) {
  627.         str = MSG_ReadString ();
  628.         if (!str[0])
  629.             break;
  630.         numsounds++;
  631.         if (numsounds == MAX_SOUNDS)
  632.             Host_EndGame ("Server sent too many sound_precache");
  633.         strcpy (cl.sound_name[numsounds], str);
  634.     }
  635.  
  636.     n = MSG_ReadByte();
  637.  
  638.     if (n) {
  639.         MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  640. //        MSG_WriteString (&cls.netchan.message, va("soundlist %i %i", cl.servercount, n));
  641.         MSG_WriteString (&cls.netchan.message, va(soundlist_name, cl.servercount, n));
  642.         return;
  643.     }
  644.  
  645.     cls.downloadnumber = 0;
  646.     cls.downloadtype = dl_sound;
  647.     Sound_NextDownload ();
  648. }
  649.  
  650. /*
  651. ==================
  652. CL_ParseModellist
  653. ==================
  654. */
  655. void CL_ParseModellist (void)
  656. {
  657.     int    nummodels;
  658.     char    *str;
  659.     int n;
  660.  
  661. // precache models and note certain default indexes
  662.     nummodels = MSG_ReadByte();
  663.  
  664.     for (;;)
  665.     {
  666.         str = MSG_ReadString ();
  667.         if (!str[0])
  668.             break;
  669.         nummodels++;
  670.         if (nummodels==MAX_MODELS)
  671.             Host_EndGame ("Server sent too many model_precache");
  672.         strcpy (cl.model_name[nummodels], str);
  673.  
  674.         if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl"))
  675.             cl_spikeindex = nummodels;
  676.         if (!strcmp(cl.model_name[nummodels],"progs/player.mdl"))
  677.             cl_playerindex = nummodels;
  678.         if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl"))
  679.             cl_flagindex = nummodels;
  680.     }
  681.  
  682.     n = MSG_ReadByte();
  683.  
  684.     if (n) {
  685.         MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  686. //        MSG_WriteString (&cls.netchan.message, va("modellist %i %i", cl.servercount, n));
  687.         MSG_WriteString (&cls.netchan.message, va(modellist_name, cl.servercount, n));
  688.         return;
  689.     }
  690.  
  691.     cls.downloadnumber = 0;
  692.     cls.downloadtype = dl_model;
  693.     Model_NextDownload ();
  694. }
  695.  
  696. /*
  697. ==================
  698. CL_ParseBaseline
  699. ==================
  700. */
  701. void CL_ParseBaseline (entity_state_t *es)
  702. {
  703.     int            i;
  704.     
  705.     es->modelindex = MSG_ReadByte ();
  706.     es->frame = MSG_ReadByte ();
  707.     es->colormap = MSG_ReadByte();
  708.     es->skinnum = MSG_ReadByte();
  709.     for (i=0 ; i<3 ; i++)
  710.     {
  711.         es->origin[i] = MSG_ReadCoord ();
  712.         es->angles[i] = MSG_ReadAngle ();
  713.     }
  714. }
  715.  
  716.  
  717.  
  718. /*
  719. =====================
  720. CL_ParseStatic
  721.  
  722. Static entities are non-interactive world objects
  723. like torches
  724. =====================
  725. */
  726. void CL_ParseStatic (void)
  727. {
  728.     entity_t *ent;
  729.     int        i;
  730.     entity_state_t    es;
  731.  
  732.     CL_ParseBaseline (&es);
  733.         
  734.     i = cl.num_statics;
  735.     if (i >= MAX_STATIC_ENTITIES)
  736.         Host_EndGame ("Too many static entities");
  737.     ent = &cl_static_entities[i];
  738.     cl.num_statics++;
  739.  
  740. // copy it to the current state
  741.     ent->model = cl.model_precache[es.modelindex];
  742.     ent->frame = es.frame;
  743.     ent->colormap = vid.colormap;
  744.     ent->skinnum = es.skinnum;
  745.  
  746.     VectorCopy (es.origin, ent->origin);
  747.     VectorCopy (es.angles, ent->angles);
  748.     
  749.     R_AddEfrags (ent);
  750. }
  751.  
  752. /*
  753. ===================
  754. CL_ParseStaticSound
  755. ===================
  756. */
  757. void CL_ParseStaticSound (void)
  758. {
  759.     vec3_t        org;
  760.     int            sound_num, vol, atten;
  761.     int            i;
  762.     
  763.     for (i=0 ; i<3 ; i++)
  764.         org[i] = MSG_ReadCoord ();
  765.     sound_num = MSG_ReadByte ();
  766.     vol = MSG_ReadByte ();
  767.     atten = MSG_ReadByte ();
  768.     
  769.     S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
  770. }
  771.  
  772.  
  773.  
  774. /*
  775. =====================================================================
  776.  
  777. ACTION MESSAGES
  778.  
  779. =====================================================================
  780. */
  781.  
  782. /*
  783. ==================
  784. CL_ParseStartSoundPacket
  785. ==================
  786. */
  787. void CL_ParseStartSoundPacket(void)
  788. {
  789.     vec3_t  pos;
  790.     int     channel, ent;
  791.     int     sound_num;
  792.     int     volume;
  793.     float     attenuation;  
  794.      int        i;
  795.                
  796.     channel = MSG_ReadShort(); 
  797.  
  798.     if (channel & SND_VOLUME)
  799.         volume = MSG_ReadByte ();
  800.     else
  801.         volume = DEFAULT_SOUND_PACKET_VOLUME;
  802.     
  803.     if (channel & SND_ATTENUATION)
  804.         attenuation = MSG_ReadByte () / 64.0;
  805.     else
  806.         attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
  807.     
  808.     sound_num = MSG_ReadByte ();
  809.  
  810.     for (i=0 ; i<3 ; i++)
  811.         pos[i] = MSG_ReadCoord ();
  812.  
  813.     ent = (channel>>3)&1023;
  814.     channel &= 7;
  815.  
  816.     if (ent > MAX_EDICTS)
  817.         Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent);
  818.     
  819.     S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
  820. }       
  821.  
  822.  
  823. /*
  824. ==================
  825. CL_ParseClientdata
  826.  
  827. Server information pertaining to this client only, sent every frame
  828. ==================
  829. */
  830. void CL_ParseClientdata (void)
  831. {
  832.     int                i;
  833.     float        latency;
  834.     frame_t        *frame;
  835.  
  836. // calculate simulated time of message
  837.     oldparsecountmod = parsecountmod;
  838.  
  839.     i = cls.netchan.incoming_acknowledged;
  840.     cl.parsecount = i;
  841.     i &= UPDATE_MASK;
  842.     parsecountmod = i;
  843.     frame = &cl.frames[i];
  844.     parsecounttime = cl.frames[i].senttime;
  845.  
  846.     frame->receivedtime = realtime;
  847.  
  848. // calculate latency
  849.     latency = frame->receivedtime - frame->senttime;
  850.  
  851.     if (latency < 0 || latency > 1.0)
  852.     {
  853. //        Con_Printf ("Odd latency: %5.2f\n", latency);
  854.     }
  855.     else
  856.     {
  857.     // drift the average latency towards the observed latency
  858.         if (latency < cls.latency)
  859.             cls.latency = latency;
  860.         else
  861.             cls.latency += 0.001;    // drift up, so correction are needed
  862.     }    
  863. }
  864.  
  865. /*
  866. =====================
  867. CL_NewTranslation
  868. =====================
  869. */
  870. void CL_NewTranslation (int slot)
  871. {
  872. #ifdef GLQUAKE
  873.     if (slot > MAX_CLIENTS)
  874.         Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS");
  875.  
  876.     R_TranslatePlayerSkin(slot);
  877. #else
  878.  
  879.     int        i, j;
  880.     int        top, bottom;
  881.     byte    *dest, *source;
  882.     player_info_t    *player;
  883.     char s[512];
  884.  
  885.     if (slot > MAX_CLIENTS)
  886.         Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS");
  887.  
  888.     player = &cl.players[slot];
  889.  
  890.     strcpy(s, Info_ValueForKey(player->userinfo, "skin"));
  891.     COM_StripExtension(s, s);
  892.     if (player->skin && !stricmp(s, player->skin->name))
  893.         player->skin = NULL;
  894.  
  895.     if (player->_topcolor != player->topcolor ||
  896.         player->_bottomcolor != player->bottomcolor || !player->skin) {
  897.         player->_topcolor = player->topcolor;
  898.         player->_bottomcolor = player->bottomcolor;
  899.  
  900.         dest = player->translations;
  901.         source = vid.colormap;
  902.         memcpy (dest, vid.colormap, sizeof(player->translations));
  903.         top = player->topcolor;
  904.         if (top > 13 || top < 0)
  905.             top = 13;
  906.         top *= 16;
  907.         bottom = player->bottomcolor;
  908.         if (bottom > 13 || bottom < 0)
  909.             bottom = 13;
  910.         bottom *= 16;
  911.  
  912.         for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
  913.         {
  914.             if (top < 128)    // the artists made some backwards ranges.  sigh.
  915.                 memcpy (dest + TOP_RANGE, source + top, 16);
  916.             else
  917.                 for (j=0 ; j<16 ; j++)
  918.                     dest[TOP_RANGE+j] = source[top+15-j];
  919.                     
  920.             if (bottom < 128)
  921.                 memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
  922.             else
  923.                 for (j=0 ; j<16 ; j++)
  924.                     dest[BOTTOM_RANGE+j] = source[bottom+15-j];        
  925.         }
  926.     }
  927. #endif
  928. }
  929.  
  930. /*
  931. ==============
  932. CL_UpdateUserinfo
  933. ==============
  934. */
  935. void CL_ProcessUserInfo (int slot, player_info_t *player)
  936. {
  937.     strncpy (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name)-1);
  938.     player->topcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor"));
  939.     player->bottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor"));
  940.     if (Info_ValueForKey (player->userinfo, "*spectator")[0])
  941.         player->spectator = true;
  942.     else
  943.         player->spectator = false;
  944.  
  945.     if (cls.state == ca_active)
  946.         Skin_Find (player);
  947.  
  948.     Sbar_Changed ();
  949.     CL_NewTranslation (slot);
  950. }
  951.  
  952. /*
  953. ==============
  954. CL_UpdateUserinfo
  955. ==============
  956. */
  957. void CL_UpdateUserinfo (void)
  958. {
  959.     int        slot;
  960.     player_info_t    *player;
  961.  
  962.     slot = MSG_ReadByte ();
  963.     if (slot >= MAX_CLIENTS)
  964.         Host_EndGame ("CL_ParseServerMessage: svc_updateuserinfo > MAX_SCOREBOARD");
  965.  
  966.     player = &cl.players[slot];
  967.     player->userid = MSG_ReadLong ();
  968.     strncpy (player->userinfo, MSG_ReadString(), sizeof(player->userinfo)-1);
  969.  
  970.     CL_ProcessUserInfo (slot, player);
  971. }
  972.  
  973. /*
  974. ==============
  975. CL_SetInfo
  976. ==============
  977. */
  978. void CL_SetInfo (void)
  979. {
  980.     int        slot;
  981.     player_info_t    *player;
  982.     char key[MAX_MSGLEN];
  983.     char value[MAX_MSGLEN];
  984.  
  985.     slot = MSG_ReadByte ();
  986.     if (slot >= MAX_CLIENTS)
  987.         Host_EndGame ("CL_ParseServerMessage: svc_setinfo > MAX_SCOREBOARD");
  988.  
  989.     player = &cl.players[slot];
  990.  
  991.     strncpy (key, MSG_ReadString(), sizeof(key) - 1);
  992.     key[sizeof(key) - 1] = 0;
  993.     strncpy (value, MSG_ReadString(), sizeof(value) - 1);
  994.     key[sizeof(value) - 1] = 0;
  995.  
  996.     Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value);
  997.  
  998.     Info_SetValueForKey (player->userinfo, key, value, MAX_INFO_STRING);
  999.  
  1000.     CL_ProcessUserInfo (slot, player);
  1001. }
  1002.  
  1003. /*
  1004. ==============
  1005. CL_ServerInfo
  1006. ==============
  1007. */
  1008. void CL_ServerInfo (void)
  1009. {
  1010.     int        slot;
  1011.     player_info_t    *player;
  1012.     char key[MAX_MSGLEN];
  1013.     char value[MAX_MSGLEN];
  1014.  
  1015.     strncpy (key, MSG_ReadString(), sizeof(key) - 1);
  1016.     key[sizeof(key) - 1] = 0;
  1017.     strncpy (value, MSG_ReadString(), sizeof(value) - 1);
  1018.     key[sizeof(value) - 1] = 0;
  1019.  
  1020.     Con_DPrintf("SERVERINFO: %s=%s\n", key, value);
  1021.  
  1022.     Info_SetValueForKey (cl.serverinfo, key, value, MAX_SERVERINFO_STRING);
  1023. }
  1024.  
  1025. /*
  1026. =====================
  1027. CL_SetStat
  1028. =====================
  1029. */
  1030. void CL_SetStat (int stat, int value)
  1031. {
  1032.     int    j;
  1033.     if (stat < 0 || stat >= MAX_CL_STATS)
  1034.         Sys_Error ("CL_SetStat: %i is invalid", stat);
  1035.  
  1036.     Sbar_Changed ();
  1037.     
  1038.     if (stat == STAT_ITEMS)
  1039.     {    // set flash times
  1040.         Sbar_Changed ();
  1041.         for (j=0 ; j<32 ; j++)
  1042.             if ( (value & (1<<j)) && !(cl.stats[stat] & (1<<j)))
  1043.                 cl.item_gettime[j] = cl.time;
  1044.     }
  1045.  
  1046.     cl.stats[stat] = value;
  1047. }
  1048.  
  1049. /*
  1050. ==============
  1051. CL_MuzzleFlash
  1052. ==============
  1053. */
  1054. void CL_MuzzleFlash (void)
  1055. {
  1056.     vec3_t        fv, rv, uv;
  1057.     dlight_t    *dl;
  1058.     int            i;
  1059.     player_state_t    *pl;
  1060.  
  1061.     i = MSG_ReadShort ();
  1062.  
  1063.     if ((unsigned)(i-1) >= MAX_CLIENTS)
  1064.         return;
  1065.  
  1066. #ifdef GLQUAKE
  1067.     // don't draw our own muzzle flash in gl if flashblending
  1068.     if (i-1 == cl.playernum && gl_flashblend.value)
  1069.         return;
  1070. #endif
  1071.  
  1072.     pl = &cl.frames[parsecountmod].playerstate[i-1];
  1073.  
  1074.     dl = CL_AllocDlight (i);
  1075.     VectorCopy (pl->origin,  dl->origin);
  1076.     AngleVectors (pl->viewangles, fv, rv, uv);
  1077.         
  1078.     VectorMA (dl->origin, 18, fv, dl->origin);
  1079.     dl->radius = 200 + (rand()&31);
  1080.     dl->minlight = 32;
  1081.     dl->die = cl.time + 0.1;
  1082.     dl->color[0] = 0.2;
  1083.     dl->color[1] = 0.1;
  1084.     dl->color[2] = 0.05;
  1085.     dl->color[3] = 0.7;
  1086. }
  1087.  
  1088.  
  1089. #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
  1090. /*
  1091. =====================
  1092. CL_ParseServerMessage
  1093. =====================
  1094. */
  1095. int    received_framecount;
  1096. void CL_ParseServerMessage (void)
  1097. {
  1098.     int            cmd;
  1099.     char        *s;
  1100.     int            i, j;
  1101.  
  1102.     received_framecount = host_framecount;
  1103.     cl.last_servermessage = realtime;
  1104.     CL_ClearProjectiles ();
  1105.  
  1106. //
  1107. // if recording demos, copy the message out
  1108. //
  1109.     if (cl_shownet.value == 1)
  1110.         Con_Printf ("%i ",net_message.cursize);
  1111.     else if (cl_shownet.value == 2)
  1112.         Con_Printf ("------------------\n");
  1113.  
  1114.  
  1115.     CL_ParseClientdata ();
  1116.  
  1117. //
  1118. // parse the message
  1119. //
  1120.     while (1)
  1121.     {
  1122.         if (msg_badread)
  1123.         {
  1124.             Host_EndGame ("CL_ParseServerMessage: Bad server message");
  1125.             break;
  1126.         }
  1127.  
  1128.         cmd = MSG_ReadByte ();
  1129.  
  1130.         if (cmd == -1)
  1131.         {
  1132.             msg_readcount++;    // so the EOM showner has the right value
  1133.             SHOWNET("END OF MESSAGE");
  1134.             break;
  1135.         }
  1136.  
  1137.         SHOWNET(svc_strings[cmd]);
  1138.     
  1139.     // other commands
  1140.         switch (cmd)
  1141.         {
  1142.         default:
  1143.             Host_EndGame ("CL_ParseServerMessage: Illegible server message");
  1144.             break;
  1145.             
  1146.         case svc_nop:
  1147. //            Con_Printf ("svc_nop\n");
  1148.             break;
  1149.             
  1150.         case svc_disconnect:
  1151.             if (cls.state == ca_connected)
  1152.                 Host_EndGame ("Server disconnected\n"
  1153.                     "Server version may not be compatible");
  1154.             else
  1155.                 Host_EndGame ("Server disconnected");
  1156.             break;
  1157.  
  1158.         case svc_print:
  1159.             i = MSG_ReadByte ();
  1160.             if (i == PRINT_CHAT)
  1161.             {
  1162.                 S_LocalSound ("misc/talk.wav");
  1163.                 con_ormask = 128;
  1164.             }
  1165.             Con_Printf ("%s", MSG_ReadString ());
  1166.             con_ormask = 0;
  1167.             break;
  1168.             
  1169.         case svc_centerprint:
  1170.             SCR_CenterPrint (MSG_ReadString ());
  1171.             break;
  1172.             
  1173.         case svc_stufftext:
  1174.             s = MSG_ReadString ();
  1175.             Con_DPrintf ("stufftext: %s\n", s);
  1176.             Cbuf_AddText (s);
  1177.             break;
  1178.             
  1179.         case svc_damage:
  1180.             V_ParseDamage ();
  1181.             break;
  1182.             
  1183.         case svc_serverdata:
  1184.             Cbuf_Execute ();        // make sure any stuffed commands are done
  1185.             CL_ParseServerData ();
  1186.             vid.recalc_refdef = true;    // leave full screen intermission
  1187.             break;
  1188.             
  1189.         case svc_setangle:
  1190.             for (i=0 ; i<3 ; i++)
  1191.                 cl.viewangles[i] = MSG_ReadAngle ();
  1192. //            cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0;
  1193.             break;
  1194.             
  1195.         case svc_lightstyle:
  1196.             i = MSG_ReadByte ();
  1197.             if (i >= MAX_LIGHTSTYLES)
  1198.                 Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
  1199.             Q_strcpy (cl_lightstyle[i].map,  MSG_ReadString());
  1200.             cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
  1201.             break;
  1202.             
  1203.         case svc_sound:
  1204.             CL_ParseStartSoundPacket();
  1205.             break;
  1206.             
  1207.         case svc_stopsound:
  1208.             i = MSG_ReadShort();
  1209.             S_StopSound(i>>3, i&7);
  1210.             break;
  1211.         
  1212.         case svc_updatefrags:
  1213.             Sbar_Changed ();
  1214.             i = MSG_ReadByte ();
  1215.             if (i >= MAX_CLIENTS)
  1216.                 Host_EndGame ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
  1217.             cl.players[i].frags = MSG_ReadShort ();
  1218.             break;            
  1219.  
  1220.         case svc_updateping:
  1221.             i = MSG_ReadByte ();
  1222.             if (i >= MAX_CLIENTS)
  1223.                 Host_EndGame ("CL_ParseServerMessage: svc_updateping > MAX_SCOREBOARD");
  1224.             cl.players[i].ping = MSG_ReadShort ();
  1225.             break;
  1226.             
  1227.         case svc_updatepl:
  1228.             i = MSG_ReadByte ();
  1229.             if (i >= MAX_CLIENTS)
  1230.                 Host_EndGame ("CL_ParseServerMessage: svc_updatepl > MAX_SCOREBOARD");
  1231.             cl.players[i].pl = MSG_ReadByte ();
  1232.             break;
  1233.             
  1234.         case svc_updateentertime:
  1235.         // time is sent over as seconds ago
  1236.             i = MSG_ReadByte ();
  1237.             if (i >= MAX_CLIENTS)
  1238.                 Host_EndGame ("CL_ParseServerMessage: svc_updateentertime > MAX_SCOREBOARD");
  1239.             cl.players[i].entertime = realtime - MSG_ReadFloat ();
  1240.             break;
  1241.             
  1242.         case svc_spawnbaseline:
  1243.             i = MSG_ReadShort ();
  1244.             CL_ParseBaseline (&cl_baselines[i]);
  1245.             break;
  1246.         case svc_spawnstatic:
  1247.             CL_ParseStatic ();
  1248.             break;            
  1249.         case svc_temp_entity:
  1250.             CL_ParseTEnt ();
  1251.             break;
  1252.  
  1253.         case svc_killedmonster:
  1254.             cl.stats[STAT_MONSTERS]++;
  1255.             break;
  1256.  
  1257.         case svc_foundsecret:
  1258.             cl.stats[STAT_SECRETS]++;
  1259.             break;
  1260.  
  1261.         case svc_updatestat:
  1262.             i = MSG_ReadByte ();
  1263.             j = MSG_ReadByte ();
  1264.             CL_SetStat (i, j);
  1265.             break;
  1266.         case svc_updatestatlong:
  1267.             i = MSG_ReadByte ();
  1268.             j = MSG_ReadLong ();
  1269.             CL_SetStat (i, j);
  1270.             break;
  1271.             
  1272.         case svc_spawnstaticsound:
  1273.             CL_ParseStaticSound ();
  1274.             break;
  1275.  
  1276.         case svc_cdtrack:
  1277.             cl.cdtrack = MSG_ReadByte ();
  1278.             CDAudio_Play ((byte)cl.cdtrack, true);
  1279.             break;
  1280.  
  1281.         case svc_intermission:
  1282.             cl.intermission = 1;
  1283.             cl.completed_time = realtime;
  1284.             vid.recalc_refdef = true;    // go to full screen
  1285.             for (i=0 ; i<3 ; i++)
  1286.                 cl.simorg[i] = MSG_ReadCoord ();            
  1287.             for (i=0 ; i<3 ; i++)
  1288.                 cl.simangles[i] = MSG_ReadAngle ();
  1289.             VectorCopy (vec3_origin, cl.simvel);
  1290.             break;
  1291.  
  1292.         case svc_finale:
  1293.             cl.intermission = 2;
  1294.             cl.completed_time = realtime;
  1295.             vid.recalc_refdef = true;    // go to full screen
  1296.             SCR_CenterPrint (MSG_ReadString ());            
  1297.             break;
  1298.             
  1299.         case svc_sellscreen:
  1300.             Cmd_ExecuteString ("help");
  1301.             break;
  1302.  
  1303.         case svc_smallkick:
  1304.             cl.punchangle = -2;
  1305.             break;
  1306.         case svc_bigkick:
  1307.             cl.punchangle = -4;
  1308.             break;
  1309.  
  1310.         case svc_muzzleflash:
  1311.             CL_MuzzleFlash ();
  1312.             break;
  1313.  
  1314.         case svc_updateuserinfo:
  1315.             CL_UpdateUserinfo ();
  1316.             break;
  1317.  
  1318.         case svc_setinfo:
  1319.             CL_SetInfo ();
  1320.             break;
  1321.  
  1322.         case svc_serverinfo:
  1323.             CL_ServerInfo ();
  1324.             break;
  1325.  
  1326.         case svc_download:
  1327.             CL_ParseDownload ();
  1328.             break;
  1329.  
  1330.         case svc_playerinfo:
  1331.             CL_ParsePlayerinfo ();
  1332.             break;
  1333.  
  1334.         case svc_nails:
  1335.             CL_ParseProjectiles ();
  1336.             break;
  1337.  
  1338.         case svc_chokecount:        // some preceding packets were choked
  1339.             i = MSG_ReadByte ();
  1340.             for (j=0 ; j<i ; j++)
  1341.                 cl.frames[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].receivedtime = -2;
  1342.             break;
  1343.  
  1344.         case svc_modellist:
  1345.             CL_ParseModellist ();
  1346.             break;
  1347.  
  1348.         case svc_soundlist:
  1349.             CL_ParseSoundlist ();
  1350.             break;
  1351.  
  1352.         case svc_packetentities:
  1353.             CL_ParsePacketEntities (false);
  1354.             break;
  1355.  
  1356.         case svc_deltapacketentities:
  1357.             CL_ParsePacketEntities (true);
  1358.             break;
  1359.  
  1360.         case svc_maxspeed :
  1361.             movevars.maxspeed = MSG_ReadFloat();
  1362.             break;
  1363.  
  1364.         case svc_entgravity :
  1365.             movevars.entgravity = MSG_ReadFloat();
  1366.             break;
  1367.  
  1368.         case svc_setpause:
  1369.             cl.paused = MSG_ReadByte ();
  1370.             if (cl.paused)
  1371.                 CDAudio_Pause ();
  1372.             else
  1373.                 CDAudio_Resume ();
  1374.             break;
  1375.  
  1376.         }
  1377.     }
  1378.  
  1379.     CL_SetSolidEntities ();
  1380. }
  1381.  
  1382.  
  1383.