Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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   [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  [ [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  : 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  : 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