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