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