|
|
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.