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 NET_SendMessages are skipped, and
31 NET_GetMessages 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 when a demo file runs out, or the user starts a game
45 void CL_StopPlayback (void)
47 if (!cls
.demoplayback
)
50 fclose (cls
.demofile
);
51 cls
.demoplayback
= false;
53 cls
.state
= ca_disconnected
;
63 Dumps the current net message, prefixed by the length and view angles
66 void CL_WriteDemoMessage (void)
72 len
= LittleLong (net_message
.cursize
);
73 fwrite (&len
, 4, 1, cls
.demofile
);
76 f
= LittleFloat (cl
.viewangles
[i
]);
77 fwrite (&f
, 4, 1, cls
.demofile
);
79 fwrite (net_message
.data
, net_message
.cursize
, 1, cls
.demofile
);
80 fflush (cls
.demofile
);
87 Handles recording and playback of demos, on top of NET_ code
90 int CL_GetMessage (void)
97 // decide if it is time to grab the next message
98 if (cls
.signon
== SIGNONS
) // allways grab until fully connected
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
;
110 else if ( /* cl.time > 0 && */ cl
.time
<= cl
.mtime
[0])
112 return 0; // don't need another message yet
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
++)
121 r
= fread (&f
, 4, 1, cls
.demofile
);
122 cl
.mviewangles
[0][i
] = LittleFloat (f
);
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
);
140 r
= NET_GetMessage (cls
.netcon
);
142 if (r
!= 1 && r
!= 2)
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");
152 if (cls
.demorecording
)
153 CL_WriteDemoMessage ();
163 stop recording a demo
166 void CL_Stop_f (void)
168 if (cmd_source
!= src_command
)
171 if (!cls
.demorecording
)
173 Con_Printf ("Not recording a demo.\n");
177 // write a disconnect message to the demo file
178 SZ_Clear (&net_message
);
179 MSG_WriteByte (&net_message
, svc_disconnect
);
180 CL_WriteDemoMessage ();
183 fclose (cls
.demofile
);
185 cls
.demorecording
= false;
186 Con_Printf ("Completed demo\n");
193 record <demoname> <map> [cd track]
196 void CL_Record_f (void)
199 char name
[MAX_OSPATH
];
202 if (cmd_source
!= src_command
)
206 if (c
!= 2 && c
!= 3 && c
!= 4)
208 Con_Printf ("record <demoname> [<map> [cd track]]\n");
212 if (strstr(Cmd_Argv(1), ".."))
214 Con_Printf ("Relative pathnames are not allowed.\n");
218 if (c
== 2 && cls
.state
== ca_connected
)
220 Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
224 // write the forced cd track number, or -1
227 track
= atoi(Cmd_Argv(3));
228 Con_Printf ("Forcing CD track to %i\n", cls
.forcetrack
);
233 sprintf (name
, "%s/%s", com_gamedir
, Cmd_Argv(1));
239 Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command
);
242 // open the demo file
244 COM_DefaultExtension (name
, ".dem");
246 Con_Printf ("recording to %s.\n", name
);
247 cls
.demofile
= fopen (name
, "wb");
250 Con_Printf ("ERROR: couldn't open.\n");
254 cls
.forcetrack
= track
;
255 fprintf (cls
.demofile
, "%i\n", cls
.forcetrack
);
257 cls
.demorecording
= true;
268 void CL_PlayDemo_f (void)
272 qboolean neg
= false;
274 if (cmd_source
!= src_command
)
279 Con_Printf ("play <demoname> : plays a demo\n");
284 // disconnect from server
289 // open the demo file
291 strcpy (name
, Cmd_Argv(1));
292 COM_DefaultExtension (name
, ".dem");
294 Con_Printf ("Playing demo from %s.\n", name
);
295 COM_FOpenFile (name
, &cls
.demofile
);
298 Con_Printf ("ERROR: couldn't open.\n");
299 cls
.demonum
= -1; // stop demo loop
303 cls
.demoplayback
= true;
304 cls
.state
= ca_connected
;
307 while ((c
= getc(cls
.demofile
)) != '\n')
311 cls
.forcetrack
= cls
.forcetrack
* 10 + (c
- '0');
314 cls
.forcetrack
= -cls
.forcetrack
;
315 // ZOID, fscanf is evil
316 // fscanf (cls.demofile, "%i\n", &cls.forcetrack);
325 void CL_FinishTimeDemo (void)
330 cls
.timedemo
= false;
332 // the first frame didn't count
333 frames
= (host_framecount
- cls
.td_startframe
) - 1;
334 time
= realtime
- cls
.td_starttime
;
337 Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames
, time
, frames
/time
);
347 void CL_TimeDemo_f (void)
349 if (cmd_source
!= src_command
)
354 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
360 // cls.td_starttime will be grabbed at the second frame of the demo, so
361 // all the loading time doesn't get counted
364 cls
.td_startframe
= host_framecount
;
365 cls
.td_lastframe
= -1; // get a new message this frame