1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CL_DEMO_H
#define CL_DEMO_H
#ifdef _WIN32
#pragma once
#endif
#include "demofile.h"
#include "cl_demoactionmanager.h"
struct DemoCommandQueue
{
DemoCommandQueue()
{
tick = 0;
}
int tick;
democmdinfo_t info;
int filepos;
};
// When skipping forward through a replay it is important to stop
// occasionally and process the backlog of packets. Otherwise if you
// skip forward too far you will cause data structures to grow far
// beyond their intended size. This can lead to overflows and out-of-memory
// errors, and it can waste memory because some of these data structures
// never release their memory after hitting a high-water mark.
const unsigned nMaxConsecutiveSkipPackets = 100;
class CDemoPlayer : public IDemoPlayer
{
public: // IDemoPlayer interface implementation:
CDemoPlayer();
~CDemoPlayer();
virtual CDemoFile *GetDemoFile();
virtual bool StartPlayback( const char *filename, bool bAsTimeDemo );
virtual void PausePlayback( float seconds );
virtual void SkipToTick( int tick, bool bRelative, bool bPause );
virtual void SetEndTick( int tick );
virtual void ResumePlayback( void );
virtual void StopPlayback( void );
virtual int GetPlaybackStartTick( void );
virtual int GetPlaybackTick( void );
virtual float GetPlaybackTimeScale( void );
virtual int GetTotalTicks( void );
virtual bool IsPlayingBack( void );
virtual bool IsPlaybackPaused( void );
virtual bool IsPlayingTimeDemo( void );
virtual bool IsSkipping( void );
virtual bool CanSkipBackwards( void ) { return false; }
virtual void SetPlaybackTimeScale( float timescale );
virtual void InterpolateViewpoint(); // override viewpoint
virtual netpacket_t *ReadPacket( void );
virtual void ResetDemoInterpolation( void );
virtual int GetProtocolVersion();
virtual bool ShouldLoopDemos() { return true; }
virtual void OnLastDemoInLoopPlayed() {}
virtual bool IsLoading( void );
public: // other public functions
void MarkFrame( float flFPSVariability );
void SetBenchframe( int tick, const char *filename );
void ResyncDemoClock( void );
bool CheckPausedPlayback( void );
void WriteTimeDemoResults( void );
bool ParseAheadForInterval( int curtick, int intervalticks );
void InterpolateDemoCommand( int targettick, DemoCommandQueue& prev, DemoCommandQueue& next );
protected:
bool OverrideView( democmdinfo_t& info );
virtual void OnStopCommand();
public:
CDemoFile m_DemoFile;
int m_nStartTick; // For synchronizing playback during timedemo.
int m_nPreviousTick;
netpacket_t m_DemoPacket; // last read demo packet
bool m_bPlayingBack; // true if demo playback
bool m_bPlaybackPaused; // true if demo is paused right now
float m_flAutoResumeTime; // how long do we pause demo playback
float m_flPlaybackRateModifier;
int m_nSkipToTick; // skip to tick ASAP, -1 = off
int m_nEndTick; // if nonzero, stop playback once we reach this tick
bool m_bLoading; // true if demo is loading
unsigned m_nSkipPacketsPlayed; // Track consecutive skip packets returned to avoid excess
// view origin/angle interpolation:
CUtlVector< DemoCommandQueue > m_DestCmdInfo;
democmdinfo_t m_LastCmdInfo;
bool m_bInterpolateView;
bool m_bResetInterpolation;
// timedemo stuff:
bool m_bTimeDemo; // ture if in timedemo mode
int m_nTimeDemoStartFrame; // host_tickcount at start
double m_flTimeDemoStartTime; // Sys_FloatTime() at second frame of timedemo
float m_flTotalFPSVariability; // Frame rate variability
int m_nTimeDemoCurrentFrame; // last frame we read a packet
// benchframe stuff
int m_nSnapshotTick;
char m_SnapshotFilename[MAX_OSPATH];
};
class CDemoRecorder : public IDemoRecorder
{
public:
~CDemoRecorder();
CDemoRecorder();
CDemoFile *GetDemoFile( void );
int GetRecordingTick( void );
void StartRecording( const char *filename, bool bContinuously );
void SetSignonState( int state );
bool IsRecording( void );
void PauseRecording( void );
void ResumeRecording( void );
void StopRecording( void );
void RecordCommand( const char *cmdstring ); // record a console command
void RecordUserInput( int cmdnumber ); // record a user input command
void RecordMessages( bf_read &data, int bits ); // add messages to current packet
void RecordPacket( void ); // packet finished, write all recorded stuff to file
void RecordServerClasses( ServerClass *pClasses ); // packet finished, write all recorded stuff to file
void RecordStringTables();
void ResetDemoInterpolation( void );
protected:
void ResyncDemoClock( void );
void StartupDemoFile( void );
void StartupDemoHeader( void );
void CloseDemoFile( void );
void GetClientCmdInfo( democmdinfo_t& info );
void WriteDemoCvars( void );
void WriteBSPDecals( void );
void WriteMessages( bf_write &message );
bool ComputeNextIncrementalDemoFilename( char *name, int namesize );
public:
CDemoFile m_DemoFile;
// For synchronizing playback during timedemo.
int m_nStartTick; // host_tickcount when starting recoring
// Name of demo file we are appending onto.
char m_szDemoBaseName[ MAX_OSPATH ];
// For demo file handle
bool m_bIsDemoHeader; // true, if m_hDemoFile is the header file
bool m_bCloseDemoFile; // if true, demo file will be closed ASAP
bool m_bRecording; // true if recording
bool m_bContinuously; // start new record after each
int m_nDemoNumber; // demo count, increases each changelevel
int m_nFrameCount; // # of demo frames in this segment.
bf_write m_MessageData; // temp buffer for all network messages
bool m_bResetInterpolation;
};
extern CDemoRecorder *g_pClientDemoRecorder;
inline CDemoPlayer *ToClientDemoPlayer( IDemoPlayer *pDemoPlayer )
{
return static_cast< CDemoPlayer * >( pDemoPlayer );
}
#endif // CL_DEMO_H
|