1#ifndef GAME_SERVER_TEEHISTORIAN_H
2#define GAME_SERVER_TEEHISTORIAN_H
3
4#include <base/hash.h>
5
6#include <engine/console.h>
7#include <engine/shared/protocol.h>
8
9#include <generated/protocol.h>
10
11#include <ctime>
12
13class CConfig;
14class CTuningParams;
15class CUuidManager;
16
17class CTeeHistorian
18{
19public:
20 typedef void (*WRITE_CALLBACK)(const void *pData, int DataSize, void *pUser);
21
22 struct CGameInfo
23 {
24 CUuid m_GameUuid;
25 const char *m_pServerVersion;
26 time_t m_StartTime;
27 const char *m_pPrngDescription;
28
29 const char *m_pServerName;
30 int m_ServerPort;
31 const char *m_pGameType;
32
33 const char *m_pMapName;
34 int m_MapSize;
35 SHA256_DIGEST m_MapSha256;
36 int m_MapCrc;
37
38 bool m_HavePrevGameUuid;
39 CUuid m_PrevGameUuid;
40
41 CConfig *m_pConfig;
42 CTuningParams *m_pTuning;
43 CUuidManager *m_pUuids;
44 };
45
46 enum
47 {
48 PROTOCOL_6 = 1,
49 PROTOCOL_7,
50 };
51
52 CTeeHistorian();
53
54 void Reset(const CGameInfo *pGameInfo, WRITE_CALLBACK pfnWriteCallback, void *pUser);
55 void Finish();
56
57 bool Starting() const { return m_State == STATE_START; }
58
59 void BeginTick(int Tick);
60
61 void BeginPlayers();
62 void RecordPlayer(int ClientId, const CNetObj_CharacterCore *pChar);
63 void RecordDeadPlayer(int ClientId);
64 void RecordPlayerTeam(int ClientId, int Team);
65 void RecordTeamPractice(int Team, bool Practice);
66 void EndPlayers();
67
68 void BeginInputs();
69 void RecordPlayerInput(int ClientId, uint32_t UniqueClientId, const CNetObj_PlayerInput *pInput);
70 void RecordPlayerMessage(int ClientId, const void *pMsg, int MsgSize);
71 void RecordPlayerJoin(int ClientId, int Protocol);
72 void RecordPlayerRejoin(int ClientId);
73 void RecordPlayerReady(int ClientId);
74 void RecordPlayerDrop(int ClientId, const char *pReason);
75 void RecordPlayerName(int ClientId, const char *pName);
76 void RecordConsoleCommand(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult);
77 void RecordTestExtra();
78 void RecordPlayerSwap(int ClientId1, int ClientId2);
79 void RecordTeamSaveSuccess(int Team, CUuid SaveId, const char *pTeamSave);
80 void RecordTeamSaveFailure(int Team);
81 void RecordTeamLoadSuccess(int Team, CUuid SaveId, const char *pTeamSave);
82 void RecordTeamLoadFailure(int Team);
83 void EndInputs();
84
85 void EndTick();
86
87 void RecordDDNetVersionOld(int ClientId, int DDNetVersion);
88 void RecordDDNetVersion(int ClientId, CUuid ConnectionId, int DDNetVersion, const char *pDDNetVersionStr);
89
90 void RecordAuthInitial(int ClientId, int Level, const char *pAuthName);
91 void RecordAuthLogin(int ClientId, int Level, const char *pAuthName);
92 void RecordAuthLogout(int ClientId);
93
94 void RecordAntibot(const void *pData, int DataSize);
95
96 void RecordPlayerFinish(int ClientId, int TimeTicks);
97 void RecordTeamFinish(int TeamId, int TimeTicks);
98
99 int m_Debug; // Possible values: 0, 1, 2.
100
101private:
102 void WriteHeader(const CGameInfo *pGameInfo);
103 void WriteExtra(CUuid Uuid, const void *pData, int DataSize);
104 void EnsureTickWrittenPlayerData(int ClientId);
105 void EnsureTickWritten();
106 void WriteTick();
107 void Write(const void *pData, int DataSize);
108
109 enum
110 {
111 STATE_START,
112 STATE_BEFORE_TICK,
113 STATE_BEFORE_PLAYERS,
114 STATE_PLAYERS,
115 STATE_BEFORE_INPUTS,
116 STATE_INPUTS,
117 STATE_BEFORE_ENDTICK,
118 NUM_STATES,
119 };
120
121 struct CTeehistorianPlayer
122 {
123 bool m_Alive;
124 int m_X;
125 int m_Y;
126
127 CNetObj_PlayerInput m_Input;
128 uint32_t m_UniqueClientId;
129
130 // DDNet team
131 int m_Team;
132 };
133
134 struct CTeam
135 {
136 bool m_Practice;
137 };
138
139 WRITE_CALLBACK m_pfnWriteCallback;
140 void *m_pWriteCallbackUserdata;
141
142 int m_State;
143
144 int m_LastWrittenTick;
145 bool m_TickWritten;
146 int m_Tick;
147 int m_PrevMaxClientId;
148 int m_MaxClientId;
149 CTeehistorianPlayer m_aPrevPlayers[MAX_CLIENTS];
150 CTeam m_aPrevTeams[MAX_CLIENTS];
151};
152
153#endif // GAME_SERVER_TEEHISTORIAN_H
154