DEMO CODE
-When a demo is playing back, all NET_SendMessages are skipped, and
-NET_GetMessages are read from the demo file.
+When a demo is playing back, all outgoing network messages are skipped, and
+incoming messages are read from the demo file.
Whenever cl.time gets past the last received message, another message is
read from the demo file.
Called to play the next demo in the demo loop
=====================
*/
+extern void Call_MR_ToggleMenu_f (void);
void CL_NextDemo (void)
{
char str[1024];
cls.demonum = 0;
if (!cls.demos[cls.demonum][0])
{
- Con_Printf ("No demos listed with startdemos\n");
+ Con_Print("No demos listed with startdemos\n");
cls.demonum = -1;
+ // put up menu instead of staring at console
+ if (key_dest != key_menu)
+ Call_MR_ToggleMenu_f();
return;
}
}
/*
====================
-CL_GetMessage
+CL_ReadDemoMessage
-Handles recording and playback of demos, on top of NET_ code
+Handles playback of demos
====================
*/
-int CL_GetMessage (void)
+void CL_ReadDemoMessage(void)
{
- int r, i;
- float f;
+ int r, i;
+ float f;
- if (cls.demoplayback)
- {
- if (cls.demopaused) // LordHavoc: pausedemo
- return 0;
+ if (!cls.demoplayback)
+ return;
+
+ // LordHavoc: pausedemo
+ if (cls.demopaused)
+ return;
- // decide if it is time to grab the next message
- if (cls.signon == SIGNONS) // always grab until fully connected
+ while (1)
+ {
+ // decide if it is time to grab the next message
+ // always grab until fully connected
+ if (cls.signon == SIGNONS)
{
if (cls.timedemo)
{
if (host_framecount == cls.td_lastframe)
- return 0; // already read this frame's message
+ {
+ // already read this frame's message
+ return;
+ }
+ if (cls.td_lastframe == -1)
+ {
+ // we start counting on the second frame
+ // (after parsing connection stuff)
+ cls.td_startframe = host_framecount + 1;
+ }
cls.td_lastframe = host_framecount;
- // if this is the second frame, grab the real td_starttime
- // so the bogus time on the first frame doesn't count
- if (host_framecount == cls.td_startframe + 1)
+ // if this is the first official frame we can now grab the real
+ // td_starttime so the bogus time on the first frame doesn't
+ // count against the final report
+ if (host_framecount == cls.td_startframe)
cls.td_starttime = realtime;
+ if (host_framecount > cls.td_startframe + 2)
+ {
+ cls.td_minframetime = min(cls.td_minframetime, host_realframetime);
+ cls.td_maxframetime = max(cls.td_maxframetime, host_realframetime);
+ }
+ else
+ cls.td_minframetime = cls.td_maxframetime = host_realframetime;
}
else if (cl.time <= cl.mtime[0])
{
- return 0; // don't need another message yet
+ // don't need another message yet
+ return;
}
}
- // get the next message
- FS_Read (cls.demofile, &net_message.cursize, 4);
- VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
- for (i=0 ; i<3 ; i++)
+ // get the next message
+ FS_Read(cls.demofile, &net_message.cursize, 4);
+ net_message.cursize = LittleLong(net_message.cursize);
+ if (net_message.cursize > net_message.maxsize)
+ Host_Error("Demo message (%i) > net_message.maxsize (%i)", net_message.cursize, net_message.maxsize);
+ VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
+ for (i = 0;i < 3;i++)
{
- r = FS_Read (cls.demofile, &f, 4);
- cl.mviewangles[0][i] = LittleFloat (f);
+ r = FS_Read(cls.demofile, &f, 4);
+ cl.mviewangles[0][i] = LittleFloat(f);
}
- net_message.cursize = LittleLong (net_message.cursize);
- if (net_message.cursize > MAX_DATAGRAM)
- Host_Error ("Demo message > MAX_DATAGRAM");
- r = FS_Read (cls.demofile, net_message.data, net_message.cursize);
- if (r != net_message.cursize)
+ if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == (size_t)net_message.cursize)
{
- CL_Disconnect ();
- return 0;
- }
-
- return 1;
- }
+ MSG_BeginReading();
+ CL_ParseServerMessage();
- while (1)
- {
- r = NET_GetMessage (cls.netcon);
-
- if (r != 1 && r != 2)
- return r;
-
- // discard nop keepalive message
- if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
- Con_Printf ("<-- server to client keepalive\n");
+ // In case the demo contains a "svc_disconnect" message
+ if (!cls.demoplayback)
+ return;
+ }
else
- break;
+ {
+ CL_Disconnect();
+ return;
+ }
}
-
- if (cls.demorecording)
- CL_WriteDemoMessage ();
-
- return r;
}
if (!cls.demorecording)
{
- Con_Printf ("Not recording a demo.\n");
+ Con_Print("Not recording a demo.\n");
return;
}
FS_Close (cls.demofile);
cls.demofile = NULL;
cls.demorecording = false;
- Con_Printf ("Completed demo\n");
+ Con_Print("Completed demo\n");
}
/*
c = Cmd_Argc();
if (c != 2 && c != 3 && c != 4)
{
- Con_Printf ("record <demoname> [<map> [cd track]]\n");
+ Con_Print("record <demoname> [<map> [cd track]]\n");
return;
}
if (strstr(Cmd_Argv(1), ".."))
{
- Con_Printf ("Relative pathnames are not allowed.\n");
+ Con_Print("Relative pathnames are not allowed.\n");
return;
}
if (c == 2 && cls.state == ca_connected)
{
- Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
+ Con_Print("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
return;
}
if (c == 4)
{
track = atoi(Cmd_Argv(3));
- Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
+ Con_Printf("Forcing CD track to %i\n", cls.forcetrack);
}
else
track = -1;
// get the demo name
- strncpy (name, Cmd_Argv(1), sizeof (name) - 1);
- name[sizeof (name) - 1] = '\0';
- FS_DefaultExtension (name, ".dem");
+ strlcpy (name, Cmd_Argv(1), sizeof (name));
+ FS_DefaultExtension (name, ".dem", sizeof (name));
// start the map up
if (c > 2)
Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
// open the demo file
- Con_Printf ("recording to %s.\n", name);
+ Con_Printf("recording to %s.\n", name);
cls.demofile = FS_Open (name, "wb", false);
if (!cls.demofile)
{
- Con_Printf ("ERROR: couldn't open.\n");
+ Con_Print("ERROR: couldn't open.\n");
return;
}
cls.forcetrack = track;
- FS_Printf (cls.demofile, "%i\n", cls.forcetrack);
+ FS_Printf(cls.demofile, "%i\n", cls.forcetrack);
cls.demorecording = true;
}
if (Cmd_Argc() != 2)
{
- Con_Printf ("play <demoname> : plays a demo\n");
+ Con_Print("play <demoname> : plays a demo\n");
return;
}
// disconnect from server
CL_Disconnect ();
+ Host_ShutdownServer (false);
+
+ // update networking ports (this is mainly just needed at startup)
+ NetConn_ClientFrame();
// open the demo file
- strcpy (name, Cmd_Argv(1));
- FS_DefaultExtension (name, ".dem");
+ strlcpy (name, Cmd_Argv(1), sizeof (name));
+ FS_DefaultExtension (name, ".dem", sizeof (name));
- Con_Printf ("Playing demo from %s.\n", name);
+ Con_Printf("Playing demo from %s.\n", name);
cls.demofile = FS_Open (name, "rb", false);
if (!cls.demofile)
{
- Con_Printf ("ERROR: couldn't open.\n");
+ Con_Print("ERROR: couldn't open.\n");
cls.demonum = -1; // stop demo loop
return;
}
SCR_BeginLoadingPlaque ();
+ strlcpy(cls.demoname, name, sizeof(cls.demoname));
cls.demoplayback = true;
cls.state = ca_connected;
cls.forcetrack = 0;
*/
void CL_FinishTimeDemo (void)
{
- int frames;
- double time; // LordHavoc: changed timedemo accuracy to double
+ int frames;
+ double time; // LordHavoc: changed timedemo accuracy to double
+ double fpsmin, fpsavg, fpsmax; // report min/avg/max fps
cls.timedemo = false;
// the first frame didn't count
frames = (host_framecount - cls.td_startframe) - 1;
time = realtime - cls.td_starttime;
- if (!time)
- time = 1;
- // LordHavoc: timedemo now prints out 7 digits of fraction
- Con_Printf ("%i frames %5.7f seconds %5.7f fps\n", frames, time, frames/time);
+ fpsmin = cls.td_maxframetime > 0 ? 1.0 / cls.td_maxframetime : 0;
+ fpsavg = time > 0 ? frames / time : 0;
+ fpsmax = cls.td_minframetime > 0 ? 1.0 / cls.td_minframetime : 0;
+ // LordHavoc: timedemo now prints out 7 digits of fraction, and min/avg/max
+ Con_Printf("%i frames %5.7f seconds %5.7f fps\nmin/avg/max: %5.7f/%5.7f/%5.7f\n", frames, time, fpsavg, fpsmin, fpsavg, fpsmax);
+ Log_Printf("benchmark.log", "date %s | enginedate %s | demo %s | commandline %s | result %i frames %5.7f seconds %5.7f fps min/avg/max: %5.7f/%5.7f/%5.7f\n", Sys_TimeString("%Y-%m-%d %H:%M:%S"), buildstring, cls.demoname, cmdline.string, frames, time, fpsavg, fpsmin, fpsavg, fpsmax);
+ if (COM_CheckParm("-benchmark"))
+ Host_Quit_f();
}
/*
if (Cmd_Argc() != 2)
{
- Con_Printf ("timedemo <demoname> : gets demo speeds\n");
+ Con_Print("timedemo <demoname> : gets demo speeds\n");
return;
}
scr_con_current = 0;
cls.timedemo = true;
- cls.td_startframe = host_framecount;
- cls.td_lastframe = -1; // get a new message this frame
+ // get first message this frame
+ cls.td_lastframe = -1;
}