2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
23 void CL_FinishTimeDemo (void);
26 ==============================================================================
30 When a demo is playing back, all outgoing network messages are skipped, and
31 incoming messages are read from the demo file.
33 Whenever cl.time gets past the last received message, another message is
34 read from the demo file.
35 ==============================================================================
42 Called to play the next demo in the demo loop
45 void CL_NextDemo (void)
49 if (cls.demonum == -1)
50 return; // don't play demos
52 if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
55 if (!cls.demos[cls.demonum][0])
57 Con_Printf ("No demos listed with startdemos\n");
63 sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]);
64 Cbuf_InsertText (str);
72 Called when a demo file runs out, or the user starts a game
75 // LordHavoc: now called only by CL_Disconnect
76 void CL_StopPlayback (void)
78 if (!cls.demoplayback)
81 FS_Close (cls.demofile);
82 cls.demoplayback = false;
93 Dumps the current net message, prefixed by the length and view angles
96 void CL_WriteDemoMessage (void)
102 if (cls.demopaused) // LordHavoc: pausedemo
105 len = LittleLong (net_message.cursize);
106 FS_Write (cls.demofile, &len, 4);
107 for (i=0 ; i<3 ; i++)
109 f = LittleFloat (cl.viewangles[i]);
110 FS_Write (cls.demofile, &f, 4);
112 FS_Write (cls.demofile, net_message.data, net_message.cursize);
113 FS_Flush (cls.demofile);
120 Handles playback of demos
123 void CL_ReadDemoMessage(void)
128 if (!cls.demoplayback)
131 // LordHavoc: pausedemo
135 // decide if it is time to grab the next message
136 // always grab until fully connected
137 if (cls.signon == SIGNONS)
141 if (host_framecount == cls.td_lastframe)
143 // already read this frame's message
146 if (cls.td_lastframe == -1)
148 // we start counting on the second frame
149 // (after parsing connection stuff)
150 cls.td_startframe = host_framecount + 1;
152 cls.td_lastframe = host_framecount;
153 // if this is the first official frame we can now grab the real
154 // td_starttime so the bogus time on the first frame doesn't
155 // count against the final report
156 if (host_framecount == cls.td_startframe)
157 cls.td_starttime = realtime;
159 else if (cl.time <= cl.mtime[0])
161 // don't need another message yet
166 // get the next message
167 FS_Read(cls.demofile, &net_message.cursize, 4);
168 net_message.cursize = LittleLong(net_message.cursize);
169 VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
170 for (i = 0;i < 3;i++)
172 r = FS_Read(cls.demofile, &f, 4);
173 cl.mviewangles[0][i] = LittleFloat(f);
176 if (net_message.cursize > NET_MAXMESSAGE)
177 Host_Error("Demo message > NET_MAXMESSAGE");
178 if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == (size_t)net_message.cursize)
181 CL_ParseServerMessage();
192 stop recording a demo
195 void CL_Stop_f (void)
197 if (cmd_source != src_command)
200 if (!cls.demorecording)
202 Con_Printf ("Not recording a demo.\n");
206 // write a disconnect message to the demo file
207 SZ_Clear (&net_message);
208 MSG_WriteByte (&net_message, svc_disconnect);
209 CL_WriteDemoMessage ();
212 FS_Close (cls.demofile);
214 cls.demorecording = false;
215 Con_Printf ("Completed demo\n");
222 record <demoname> <map> [cd track]
225 void CL_Record_f (void)
228 char name[MAX_OSPATH];
230 if (cmd_source != src_command)
234 if (c != 2 && c != 3 && c != 4)
236 Con_Printf ("record <demoname> [<map> [cd track]]\n");
240 if (strstr(Cmd_Argv(1), ".."))
242 Con_Printf ("Relative pathnames are not allowed.\n");
246 if (c == 2 && cls.state == ca_connected)
248 Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
252 // write the forced cd track number, or -1
255 track = atoi(Cmd_Argv(3));
256 Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
262 strlcpy (name, Cmd_Argv(1), sizeof (name));
263 FS_DefaultExtension (name, ".dem", sizeof (name));
267 Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
269 // open the demo file
270 Con_Printf ("recording to %s.\n", name);
271 cls.demofile = FS_Open (name, "wb", false);
274 Con_Printf ("ERROR: couldn't open.\n");
278 cls.forcetrack = track;
279 FS_Printf (cls.demofile, "%i\n", cls.forcetrack);
281 cls.demorecording = true;
292 void CL_PlayDemo_f (void)
296 qboolean neg = false;
298 if (cmd_source != src_command)
303 Con_Printf ("play <demoname> : plays a demo\n");
307 // disconnect from server
310 // update networking ports (this is mainly just needed at startup)
311 NetConn_ClientFrame();
313 // open the demo file
314 strlcpy (name, Cmd_Argv(1), sizeof (name));
315 FS_DefaultExtension (name, ".dem", sizeof (name));
317 Con_Printf ("Playing demo from %s.\n", name);
318 cls.demofile = FS_Open (name, "rb", false);
321 Con_Printf ("ERROR: couldn't open.\n");
322 cls.demonum = -1; // stop demo loop
326 SCR_BeginLoadingPlaque ();
328 cls.demoplayback = true;
329 cls.state = ca_connected;
332 while ((c = FS_Getc (cls.demofile)) != '\n')
336 cls.forcetrack = cls.forcetrack * 10 + (c - '0');
339 cls.forcetrack = -cls.forcetrack;
348 void CL_FinishTimeDemo (void)
351 double time; // LordHavoc: changed timedemo accuracy to double
353 cls.timedemo = false;
355 // the first frame didn't count
356 frames = (host_framecount - cls.td_startframe) - 1;
357 time = realtime - cls.td_starttime;
360 // LordHavoc: timedemo now prints out 7 digits of fraction
361 Con_Printf ("%i frames %5.7f seconds %5.7f fps\n", frames, time, frames/time);
371 void CL_TimeDemo_f (void)
373 if (cmd_source != src_command)
378 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
384 // cls.td_starttime will be grabbed at the second frame of the demo, so
385 // all the loading time doesn't get counted
387 // instantly hide console and deactivate it
389 key_consoleactive = 0;
394 // get first message this frame
395 cls.td_lastframe = -1;