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 Sys_FileClose(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 Sys_FileWrite(cls
.demofile
, &len
, 4);
76 f
= LittleFloat (cl
.viewangles
[i
]);
77 Sys_FileWrite(cls
.demofile
, &f
, 4);
79 Sys_FileWrite(cls
.demofile
, net_message
.data
, net_message
.cursize
);
86 Handles recording and playback of demos, on top of NET_ code
89 int CL_GetMessage (void)
96 // decide if it is time to grab the next message
97 if (cls
.signon
== SIGNONS
) // allways grab until fully connected
101 if (host_framecount
== cls
.td_lastframe
)
102 return 0; // allready read this frame's message
103 cls
.td_lastframe
= host_framecount
;
104 // if this is the second frame, grab the real td_starttime
105 // so the bogus time on the first frame doesn't count
106 if (host_framecount
== cls
.td_startframe
+ 1)
107 cls
.td_starttime
= realtime
;
109 else if ( /* cl.time > 0 && */ cl
.time
<= cl
.mtime
[0])
111 return 0; // don't need another message yet
115 // get the next message
116 Sys_FileRead(cls
.demofile
, &net_message
.cursize
, 4);
117 VectorCopy (cl
.mviewangles
[0], cl
.mviewangles
[1]);
118 for (i
=0 ; i
<3 ; i
++)
120 r
= Sys_FileRead(cls
.demofile
, &f
, 4) / 4;
121 cl
.mviewangles
[0][i
] = LittleFloat (f
);
124 net_message
.cursize
= LittleLong (net_message
.cursize
);
125 if (net_message
.cursize
> MAX_MSGLEN
)
126 Sys_Error ("Demo message (0x%08x) > MAX_MSGLEN (%d)", net_message
.cursize
, MAX_MSGLEN
);
127 r
= Sys_FileRead(cls
.demofile
, net_message
.data
, net_message
.cursize
) / net_message
.cursize
;
139 r
= NET_GetMessage (cls
.netcon
);
141 if (r
!= 1 && r
!= 2)
144 // discard nop keepalive message
145 if (net_message
.cursize
== 1 && net_message
.data
[0] == svc_nop
)
146 Con_Printf ("<-- server to client keepalive\n");
151 if (cls
.demorecording
)
152 CL_WriteDemoMessage ();
162 stop recording a demo
165 void CL_Stop_f (void)
167 if (cmd_source
!= src_command
)
170 if (!cls
.demorecording
)
172 Con_Printf ("Not recording a demo.\n");
176 // write a disconnect message to the demo file
177 SZ_Clear (&net_message
);
178 MSG_WriteByte (&net_message
, svc_disconnect
);
179 CL_WriteDemoMessage ();
182 Sys_FileClose(cls
.demofile
);
184 cls
.demorecording
= false;
185 Con_Printf ("Completed demo\n");
192 record <demoname> <map> [cd track]
195 void CL_Record_f (void)
198 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
= Sys_FileOpenWrite(name
);
248 if (cls
.demofile
< 0)
250 Con_Printf ("ERROR: couldn't open demo for writing.\n");
254 cls
.forcetrack
= track
;
255 sprintf(forcetrack
, "%i\n", cls
.forcetrack
);
256 Sys_FileWrite(cls
.demofile
, forcetrack
, strlen(forcetrack
));
258 cls
.demorecording
= true;
269 static int CL_FileGetChar(int handle
)
273 if (Sys_FileRead(handle
, &c
, 1) != 1)
281 void CL_PlayDemo_f (void)
285 qboolean neg
= false;
287 if (cmd_source
!= src_command
)
292 Con_Printf ("play <demoname> : plays a demo\n");
297 // disconnect from server
302 // open the demo file
304 strcpy (name
, Cmd_Argv(1));
305 COM_DefaultExtension (name
, ".dem");
307 Con_Printf ("Playing demo from %s.\n", name
);
308 COM_FOpenFile (name
, &cls
.demofile
);
309 if (cls
.demofile
< 0)
311 Con_Printf ("ERROR: couldn't open demo for reading.\n");
312 cls
.demonum
= -1; // stop demo loop
316 cls
.demoplayback
= true;
317 cls
.state
= ca_connected
;
320 while ((c
= CL_FileGetChar(cls
.demofile
)) != '\n')
324 cls
.forcetrack
= cls
.forcetrack
* 10 + (c
- '0');
327 cls
.forcetrack
= -cls
.forcetrack
;
328 // ZOID, fscanf is evil
329 // fscanf (cls.demofile, "%i\n", &cls.forcetrack);
338 void CL_FinishTimeDemo (void)
343 cls
.timedemo
= false;
345 // the first frame didn't count
346 frames
= (host_framecount
- cls
.td_startframe
) - 1;
347 time
= realtime
- cls
.td_starttime
;
350 Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames
, time
, frames
/time
);
360 void CL_TimeDemo_f (void)
362 if (cmd_source
!= src_command
)
367 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
373 // cls.td_starttime will be grabbed at the second frame of the demo, so
374 // all the loading time doesn't get counted
377 cls
.td_startframe
= host_framecount
;
378 cls
.td_lastframe
= -1; // get a new message this frame