|
|
1.1 root 1:
2: #include "quakedef.h"
3:
4: void CL_FinishTimeDemo (void);
5:
6: /*
7: ==============================================================================
8:
9: DEMO CODE
10:
11: When a demo is playing back, all NET_SendMessages are skipped, and
12: NET_GetMessages are read from the demo file.
13:
14: Whenever cl.time gets past the last received message, another message is
15: read from the demo file.
16: ==============================================================================
17: */
18:
19: /*
20: ==============
21: CL_StopPlayback
22:
23: Called when a demo file runs out, or the user starts a game
24: ==============
25: */
26: void CL_StopPlayback (void)
27: {
28: if (!cls.demoplayback)
29: return;
30:
31: fclose (cls.demofile);
32: cls.demofile = NULL;
33: cls.state = ca_disconnected;
34:
35: if (cls.timedemo)
36: CL_FinishTimeDemo ();
37: }
38:
39: /*
40: ====================
41: CL_WriteDemoMessage
42:
43: Dumps the current net message, prefixed by the length and view angles
44: ====================
45: */
46: void CL_WriteDemoMessage (void)
47: {
48: int len;
49: int i;
50: float f;
51:
52: len = LittleLong (net_message.cursize);
53: fwrite (&len, 4, 1, cls.demofile);
54: for (i=0 ; i<3 ; i++)
55: {
56: f = LittleFloat (cl.viewangles[i]);
57: fwrite (&f, 4, 1, cls.demofile);
58: }
59: fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
60: fflush (cls.demofile);
61: }
62:
63: /*
64: ====================
65: CL_GetMessage
66:
67: Handles recording and playback of demos, on top of NET_ code
68: ====================
69: */
70: int CL_GetMessage (void)
71: {
72: int r, i;
73: float f;
74:
75: if (cls.demoplayback)
76: {
77:
78: // decide if it is time to grab the next message
79: if (cls.signon == SIGNONS) // allways grab until fully connected
80: {
81: if (cls.timedemo)
82: {
83: if (host_framecount == cls.td_lastframe)
84: return 0; // allready read this frame's message
85: cls.td_lastframe = host_framecount;
86: // if this is the second frame, grab the real td_starttime
87: // so the bogus time on the first frame doesn't count
88: if (host_framecount == cls.td_startframe + 1)
89: cls.td_starttime = realtime;
90: }
91: else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
92: return 0; // don't need another message yet
93: }
94:
95: // get the next message
96: fread (&net_message.cursize, 4, 1, cls.demofile);
97: VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
98: for (i=0 ; i<3 ; i++)
99: {
100: r = fread (&f, 4, 1, cls.demofile);
101: cl.mviewangles[0][i] = LittleFloat (f);
102: }
103:
104: net_message.cursize = LittleLong (net_message.cursize);
105: if (net_message.cursize > MAX_MSGLEN)
106: Sys_Error ("Demo message > MAX_MSGLEN");
107: r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
108: if (r != 1)
109: {
110: CL_StopPlayback ();
111: return 0;
112: }
113:
114: return 1;
115: }
116:
117: while (1)
118: {
119: r = NET_GetMessage (cls.netcon);
120:
121: if (r != 1 && r != 2)
122: return r;
123:
124: // discard nop keepalive message
125: if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
126: Con_Printf ("<-- server to client keepalive\n");
127: else
128: break;
129: }
130:
131: if (cls.demorecording)
132: CL_WriteDemoMessage ();
133:
134: return r;
135: }
136:
137:
138: /*
139: ====================
140: CL_Stop_f
141:
142: stop recording a demo
143: ====================
144: */
145: void CL_Stop_f (void)
146: {
147: if (cmd_source != src_command)
148: return;
149:
150: if (!cls.demorecording)
151: {
152: Con_Printf ("Not recording a demo.\n");
153: return;
154: }
155:
156: // write a disconnect message to the demo file
157: SZ_Clear (&net_message);
158: MSG_WriteByte (&net_message, svc_disconnect);
159: CL_WriteDemoMessage ();
160:
161: // finish up
162: fclose (cls.demofile);
163: cls.demofile = NULL;
164: cls.demorecording = false;
165: Con_Printf ("Completed demo\n");
166: }
167:
168: /*
169: ====================
170: CL_Record_f
171:
172: record <demoname> <map> [cd track]
173: ====================
174: */
175: void CL_Record_f (void)
176: {
177: int c;
178: char name[MAX_OSPATH];
179: int track;
180:
181: if (cmd_source != src_command)
182: return;
183:
184: c = Cmd_Argc();
185: if (c != 3 && c != 4)
186: {
187: Con_Printf ("record <demoname> <map> [cd track]\n");
188: return;
189: }
190:
191: // write the forced cd track number, or -1
192: if (c == 4)
193: {
194: track = atoi(Cmd_Argv(3));
195: Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
196: }
197: else
198: track = -1;
199:
200: sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
201:
202: //
203: // start the map up
204: //
205: Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
206:
207: //
208: // open the demo file
209: //
210: COM_DefaultExtension (name, ".dem");
211:
212: Con_Printf ("recording to %s.\n", name);
213: cls.demofile = fopen (name, "wb");
214: if (!cls.demofile)
215: {
216: Con_Printf ("ERROR: couldn't open.\n");
217: return;
218: }
219:
220: cls.forcetrack = track;
221: fprintf (cls.demofile, "%i\n", cls.forcetrack);
222:
223: cls.demorecording = true;
224: }
225:
226:
227: /*
228: ====================
229: CL_PlayDemo_f
230:
231: play [demoname]
232: ====================
233: */
234: void CL_PlayDemo_f (void)
235: {
236: char name[256];
237:
238: if (cmd_source != src_command)
239: return;
240:
241: if (Cmd_Argc() != 2)
242: {
243: Con_Printf ("play <demoname> : plays a demo\n");
244: return;
245: }
246:
247: //
248: // disconnect from server
249: //
250: CL_Disconnect ();
251:
252: //
253: // open the demo file
254: //
255: strcpy (name, Cmd_Argv(1));
256: COM_DefaultExtension (name, ".dem");
257:
258: Con_Printf ("Playing demo from %s.\n", name);
259: COM_FOpenFile (name, &cls.demofile);
260: if (!cls.demofile)
261: {
262: Con_Printf ("ERROR: couldn't open.\n");
263: cls.demonum = -1; // stop demo loop
264: return;
265: }
266:
267: cls.demoplayback = true;
268: cls.state = ca_connected;
269: fscanf (cls.demofile, "%i\n", &cls.forcetrack);
270: }
271:
272: /*
273: ====================
274: CL_FinishTimeDemo
275:
276: ====================
277: */
278: void CL_FinishTimeDemo (void)
279: {
280: int frames;
281: float time;
282:
283: cls.timedemo = false;
284:
285: // the first frame didn't count
286: frames = (host_framecount - cls.td_startframe) - 1;
287: time = realtime - cls.td_starttime;
288: if (!time)
289: time = 1;
290: Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
291: }
292:
293: /*
294: ====================
295: CL_TimeDemo_f
296:
297: timedemo [demoname]
298: ====================
299: */
300: void CL_TimeDemo_f (void)
301: {
302: if (cmd_source != src_command)
303: return;
304:
305: if (Cmd_Argc() != 2)
306: {
307: Con_Printf ("timedemo <demoname> : gets demo speeds\n");
308: return;
309: }
310:
311: CL_PlayDemo_f ();
312:
1.1.1.2 ! root 313: if (cls.signon != SIGNONS)
! 314: return;
! 315:
1.1 root 316: // cls.td_starttime will be grabbed at the second frame of the demo, so
317: // all the loading time doesn't get counted
318:
319: cls.timedemo = true;
320: cls.td_startframe = host_framecount;
321: cls.td_lastframe = -1; // get a new message this frame
322: }
323:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.