home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / glquake_src / cl_demo.c < prev    next >
C/C++ Source or Header  |  2000-01-02  |  8KB  |  378 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.  
  21. #include "quakedef.h"
  22.  
  23. void CL_FinishTimeDemo (void);
  24.  
  25. /*
  26. ==============================================================================
  27.  
  28. DEMO CODE
  29.  
  30. When a demo is playing back, all NET_SendMessages are skipped, and
  31. NET_GetMessages are read from the demo file.
  32.  
  33. Whenever cl.time gets past the last received message, another message is
  34. read from the demo file.
  35. ==============================================================================
  36. */
  37.  
  38. /*
  39. ==============
  40. CL_StopPlayback
  41.  
  42. Called when a demo file runs out, or the user starts a game
  43. ==============
  44. */
  45. void CL_StopPlayback (void)
  46. {
  47.   if (!cls.demoplayback)
  48.     return;
  49.  
  50. #ifdef AMIGA
  51.   if (cls.demofile) fclose(cls.demofile);
  52.     cls.demofile=0;
  53. #else
  54.   fclose (cls.demofile);
  55. #endif
  56.   cls.demoplayback = false;
  57.   cls.demofile = NULL;
  58.   cls.state = ca_disconnected;
  59.  
  60.   if (cls.timedemo)
  61.     CL_FinishTimeDemo ();
  62. }
  63.  
  64. /*
  65. ====================
  66. CL_WriteDemoMessage
  67.  
  68. Dumps the current net message, prefixed by the length and view angles
  69. ====================
  70. */
  71. void CL_WriteDemoMessage (void)
  72. {
  73.   int   len;
  74.   int   i;
  75.   float f;
  76.  
  77.   len = LittleLong (net_message.cursize);
  78.   fwrite (&len, 4, 1, cls.demofile);
  79.   for (i=0 ; i<3 ; i++)
  80.   {
  81.     f = LittleFloat (cl.viewangles[i]);
  82.     fwrite (&f, 4, 1, cls.demofile);
  83.   }
  84.   fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
  85.   fflush (cls.demofile);
  86. }
  87.  
  88. /*
  89. ====================
  90. CL_GetMessage
  91.  
  92. Handles recording and playback of demos, on top of NET_ code
  93. ====================
  94. */
  95. int CL_GetMessage (void)
  96. {
  97.   int   r, i;
  98.   float f;
  99.   
  100.   if  (cls.demoplayback)
  101.   {
  102.   // decide if it is time to grab the next message    
  103.     if (cls.signon == SIGNONS)  // allways grab until fully connected
  104.     {
  105.       if (cls.timedemo)
  106.       {
  107.         if (host_framecount == cls.td_lastframe)
  108.           return 0;   // allready read this frame's message
  109.         cls.td_lastframe = host_framecount;
  110.       // if this is the second frame, grab the real td_starttime
  111.       // so the bogus time on the first frame doesn't count
  112.         if (host_framecount == cls.td_startframe + 1)
  113.           cls.td_starttime = realtime;
  114.       }
  115.       else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
  116.       {
  117.           return 0;   // don't need another message yet
  118.       }
  119.     }
  120.     
  121.   // get the next message
  122.     fread (&net_message.cursize, 4, 1, cls.demofile);
  123.     VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
  124.     for (i=0 ; i<3 ; i++)
  125.     {
  126.       r = fread (&f, 4, 1, cls.demofile);
  127.       cl.mviewangles[0][i] = LittleFloat (f);
  128.     }
  129.     
  130.     net_message.cursize = LittleLong (net_message.cursize);
  131.     if (net_message.cursize > MAX_MSGLEN)
  132.       Sys_Error ("Demo message > MAX_MSGLEN");
  133.     r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
  134.     if (r != 1)
  135.     {
  136.       CL_StopPlayback ();
  137.       return 0;
  138.     }
  139.   
  140.     return 1;
  141.   }
  142.  
  143.   while (1)
  144.   {
  145.     r = NET_GetMessage (cls.netcon);
  146.     
  147.     if (r != 1 && r != 2)
  148.       return r;
  149.   
  150.   // discard nop keepalive message
  151.     if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
  152.       Con_Printf ("<-- server to client keepalive\n");
  153.     else
  154.       break;
  155.   }
  156.  
  157.   if (cls.demorecording)
  158.     CL_WriteDemoMessage ();
  159.   
  160.   return r;
  161. }
  162.  
  163.  
  164. /*
  165. ====================
  166. CL_Stop_f
  167.  
  168. stop recording a demo
  169. ====================
  170. */
  171. void CL_Stop_f (void)
  172. {
  173.   if (cmd_source != src_command)
  174.     return;
  175.  
  176.   if (!cls.demorecording)
  177.   {
  178.     Con_Printf ("Not recording a demo.\n");
  179.     return;
  180.   }
  181.  
  182. // write a disconnect message to the demo file
  183.   SZ_Clear (&net_message);
  184.   MSG_WriteByte (&net_message, svc_disconnect);
  185.   CL_WriteDemoMessage ();
  186.  
  187. // finish up
  188. #ifdef AMIGA
  189.   if (cls.demofile) fclose(cls.demofile);
  190.     cls.demofile=0;
  191. #else
  192.   fclose (cls.demofile);
  193. #endif
  194.   cls.demofile = NULL;
  195.   cls.demorecording = false;
  196.   Con_Printf ("Completed demo\n");
  197. }
  198.  
  199. /*
  200. ====================
  201. CL_Record_f
  202.  
  203. record <demoname> <map> [cd track]
  204. ====================
  205. */
  206. void CL_Record_f (void)
  207. {
  208.   int   c;
  209.   char  name[MAX_OSPATH];
  210.   int   track;
  211.  
  212.   if (cmd_source != src_command)
  213.     return;
  214.  
  215.   c = Cmd_Argc();
  216.   if (c != 2 && c != 3 && c != 4)
  217.   {
  218.     Con_Printf ("record <demoname> [<map> [cd track]]\n");
  219.     return;
  220.   }
  221.  
  222.   if (strstr(Cmd_Argv(1), ".."))
  223.   {
  224.     Con_Printf ("Relative pathnames are not allowed.\n");
  225.     return;
  226.   }
  227.  
  228.   if (c == 2 && cls.state == ca_connected)
  229.   {
  230.     Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
  231.     return;
  232.   }
  233.  
  234. // write the forced cd track number, or -1
  235.   if (c == 4)
  236.   {
  237.     track = atoi(Cmd_Argv(3));
  238.     Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
  239.   }
  240.   else
  241.     track = -1; 
  242.  
  243.   sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
  244.   
  245. //
  246. // start the map up
  247. //
  248.   if (c > 2)
  249.     Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
  250.   
  251. //
  252. // open the demo file
  253. //
  254.   COM_DefaultExtension (name, ".dem");
  255.  
  256.   Con_Printf ("recording to %s.\n", name);
  257.   cls.demofile = fopen (name, "wb");
  258.   if (!cls.demofile)
  259.   {
  260.     Con_Printf ("ERROR: couldn't open.\n");
  261.     return;
  262.   }
  263.  
  264.   cls.forcetrack = track;
  265.   fprintf (cls.demofile, "%i\n", cls.forcetrack);
  266.   
  267.   cls.demorecording = true;
  268. }
  269.  
  270.  
  271. /*
  272. ====================
  273. CL_PlayDemo_f
  274.  
  275. play [demoname]
  276. ====================
  277. */
  278. void CL_PlayDemo_f (void)
  279. {
  280.   char  name[256];
  281.   int c;
  282.   qboolean neg = false;
  283.  
  284.   if (cmd_source != src_command)
  285.     return;
  286.  
  287.   if (Cmd_Argc() != 2)
  288.   {
  289.     Con_Printf ("play <demoname> : plays a demo\n");
  290.     return;
  291.   }
  292.  
  293. //
  294. // disconnect from server
  295. //
  296.   CL_Disconnect ();
  297.   
  298. //
  299. // open the demo file
  300. //
  301.   strcpy (name, Cmd_Argv(1));
  302.   COM_DefaultExtension (name, ".dem");
  303.  
  304.   Con_Printf ("Playing demo from %s.\n", name);
  305.   COM_FOpenFile (name, &cls.demofile);
  306.   if (!cls.demofile)
  307.   {
  308.     Con_Printf ("ERROR: couldn't open.\n");
  309.     cls.demonum = -1;   // stop demo loop
  310.     return;
  311.   }
  312.  
  313.   cls.demoplayback = true;
  314.   cls.state = ca_connected;
  315.   cls.forcetrack = 0;
  316.  
  317.   while ((c = getc(cls.demofile)) != '\n')
  318.     if (c == '-')
  319.       neg = true;
  320.     else
  321.       cls.forcetrack = cls.forcetrack * 10 + (c - '0');
  322.  
  323.   if (neg)
  324.     cls.forcetrack = -cls.forcetrack;
  325. // ZOID, fscanf is evil
  326. //  fscanf (cls.demofile, "%i\n", &cls.forcetrack);
  327. }
  328.  
  329. /*
  330. ====================
  331. CL_FinishTimeDemo
  332.  
  333. ====================
  334. */
  335. void CL_FinishTimeDemo (void)
  336. {
  337.   int   frames;
  338.   float time;
  339.   
  340.   cls.timedemo = false;
  341.   
  342. // the first frame didn't count
  343.   frames = (host_framecount - cls.td_startframe) - 1;
  344.   time = realtime - cls.td_starttime;
  345.   if (!time)
  346.     time = 1;
  347.   Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
  348. }
  349.  
  350. /*
  351. ====================
  352. CL_TimeDemo_f
  353.  
  354. timedemo [demoname]
  355. ====================
  356. */
  357. void CL_TimeDemo_f (void)
  358. {
  359.   if (cmd_source != src_command)
  360.     return;
  361.  
  362.   if (Cmd_Argc() != 2)
  363.   {
  364.     Con_Printf ("timedemo <demoname> : gets demo speeds\n");
  365.     return;
  366.   }
  367.  
  368.   CL_PlayDemo_f ();
  369.   
  370. // cls.td_starttime will be grabbed at the second frame of the demo, so
  371. // all the loading time doesn't get counted
  372.   
  373.   cls.timedemo = true;
  374.   cls.td_startframe = host_framecount;
  375.   cls.td_lastframe = -1;    // get a new message this frame
  376. }
  377.  
  378.