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