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
137 // decide if it is time to grab the next message
138 // always grab until fully connected
139 if (cls.signon == SIGNONS)
143 if (host_framecount == cls.td_lastframe)
145 // already read this frame's message
148 if (cls.td_lastframe == -1)
150 // we start counting on the second frame
151 // (after parsing connection stuff)
152 cls.td_startframe = host_framecount + 1;
154 cls.td_lastframe = host_framecount;
155 // if this is the first official frame we can now grab the real
156 // td_starttime so the bogus time on the first frame doesn't
157 // count against the final report
158 if (host_framecount == cls.td_startframe)
159 cls.td_starttime = realtime;
161 else if (cl.time <= cl.mtime[0])
163 // don't need another message yet
168 // get the next message
169 FS_Read(cls.demofile, &net_message.cursize, 4);
170 net_message.cursize = LittleLong(net_message.cursize);
171 VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
172 for (i = 0;i < 3;i++)
174 r = FS_Read(cls.demofile, &f, 4);
175 cl.mviewangles[0][i] = LittleFloat(f);
178 if (net_message.cursize > NET_MAXMESSAGE)
179 Host_Error("Demo message > NET_MAXMESSAGE");
180 if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == (size_t)net_message.cursize)
183 CL_ParseServerMessage();
198 stop recording a demo
201 void CL_Stop_f (void)
203 if (cmd_source != src_command)
206 if (!cls.demorecording)
208 Con_Printf ("Not recording a demo.\n");
212 // write a disconnect message to the demo file
213 SZ_Clear (&net_message);
214 MSG_WriteByte (&net_message, svc_disconnect);
215 CL_WriteDemoMessage ();
218 FS_Close (cls.demofile);
220 cls.demorecording = false;
221 Con_Printf ("Completed demo\n");
228 record <demoname> <map> [cd track]
231 void CL_Record_f (void)
234 char name[MAX_OSPATH];
236 if (cmd_source != src_command)
240 if (c != 2 && c != 3 && c != 4)
242 Con_Printf ("record <demoname> [<map> [cd track]]\n");
246 if (strstr(Cmd_Argv(1), ".."))
248 Con_Printf ("Relative pathnames are not allowed.\n");
252 if (c == 2 && cls.state == ca_connected)
254 Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
258 // write the forced cd track number, or -1
261 track = atoi(Cmd_Argv(3));
262 Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
268 strlcpy (name, Cmd_Argv(1), sizeof (name));
269 FS_DefaultExtension (name, ".dem", sizeof (name));
273 Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
275 // open the demo file
276 Con_Printf ("recording to %s.\n", name);
277 cls.demofile = FS_Open (name, "wb", false);
280 Con_Printf ("ERROR: couldn't open.\n");
284 cls.forcetrack = track;
285 FS_Printf (cls.demofile, "%i\n", cls.forcetrack);
287 cls.demorecording = true;
298 void CL_PlayDemo_f (void)
302 qboolean neg = false;
304 if (cmd_source != src_command)
309 Con_Printf ("play <demoname> : plays a demo\n");
313 // disconnect from server
316 // update networking ports (this is mainly just needed at startup)
317 NetConn_ClientFrame();
319 // open the demo file
320 strlcpy (name, Cmd_Argv(1), sizeof (name));
321 FS_DefaultExtension (name, ".dem", sizeof (name));
323 Con_Printf ("Playing demo from %s.\n", name);
324 cls.demofile = FS_Open (name, "rb", false);
327 Con_Printf ("ERROR: couldn't open.\n");
328 cls.demonum = -1; // stop demo loop
332 SCR_BeginLoadingPlaque ();
334 cls.demoplayback = true;
335 cls.state = ca_connected;
338 while ((c = FS_Getc (cls.demofile)) != '\n')
342 cls.forcetrack = cls.forcetrack * 10 + (c - '0');
345 cls.forcetrack = -cls.forcetrack;
354 void CL_FinishTimeDemo (void)
357 double time; // LordHavoc: changed timedemo accuracy to double
359 cls.timedemo = false;
361 // the first frame didn't count
362 frames = (host_framecount - cls.td_startframe) - 1;
363 time = realtime - cls.td_starttime;
366 // LordHavoc: timedemo now prints out 7 digits of fraction
367 Con_Printf ("%i frames %5.7f seconds %5.7f fps\n", frames, time, frames/time);
377 void CL_TimeDemo_f (void)
379 if (cmd_source != src_command)
384 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
390 // cls.td_starttime will be grabbed at the second frame of the demo, so
391 // all the loading time doesn't get counted
393 // instantly hide console and deactivate it
395 key_consoleactive = 0;
400 // get first message this frame
401 cls.td_lastframe = -1;