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 RecordPlayerName(int ClientId, const char *pName);
74 void RecordConsoleCommand(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult);
75 void RecordTestExtra();
76 void RecordPlayerSwap(int ClientId1, int ClientId2);
77 void RecordTeamSaveSuccess(int Team, CUuid SaveId, const char *pTeamSave);
78 void RecordTeamSaveFailure(int Team);
79 void RecordTeamLoadSuccess(int Team, CUuid SaveId, const char *pTeamSave);
80 void RecordTeamLoadFailure(int Team);
81 void EndInputs();
82
83 void EndTick();
84
85 void RecordDDNetVersionOld(int ClientId, int DDNetVersion);
86 void RecordDDNetVersion(int ClientId, CUuid ConnectionId, int DDNetVersion, const char *pDDNetVersionStr);
87
88 void RecordAuthInitial(int ClientId, int Level, const char *pAuthName);
89 void RecordAuthLogin(int ClientId, int Level, const char *pAuthName);
90 void RecordAuthLogout(int ClientId);
91
92 void RecordAntibot(const void *pData, int DataSize);
93
94 void RecordPlayerFinish(int ClientId, int TimeTicks);
95 void RecordTeamFinish(int TeamId, int TimeTicks);
96
97 int m_Debug; // Possible values: 0, 1, 2.
98
99private:
100 void WriteHeader(const CGameInfo *pGameInfo);
101 void WriteExtra(CUuid Uuid, const void *pData, int DataSize);
102 void EnsureTickWrittenPlayerData(int ClientId);
103 void EnsureTickWritten();
104 void WriteTick();
105 void Write(const void *pData, int DataSize);
106
107 enum
108 {
109 STATE_START,
110 STATE_BEFORE_TICK,
111 STATE_BEFORE_PLAYERS,
112 STATE_PLAYERS,
113 STATE_BEFORE_INPUTS,
114 STATE_INPUTS,
115 STATE_BEFORE_ENDTICK,
116 NUM_STATES,
117 };
118
119 struct CTeehistorianPlayer
120 {
121 bool m_Alive;
122 int m_X;
123 int m_Y;
124
125 CNetObj_PlayerInput m_Input;
126 uint32_t m_UniqueClientId;
127
128 // DDNet team
129 int m_Team;
130 };
131
132 struct CTeam
133 {
134 bool m_Practice;
135 };
136
137 WRITE_CALLBACK m_pfnWriteCallback;
138 void *m_pWriteCallbackUserdata;
139
140 int m_State;
141
142 int m_LastWrittenTick;
143 bool m_TickWritten;
144 int m_Tick;
145 int m_PrevMaxClientId;
146 int m_MaxClientId;
147 CTeehistorianPlayer m_aPrevPlayers[MAX_CLIENTS];
148 CTeam m_aPrevTeams[MAX_CLIENTS];
149};
150
151#endif // GAME_SERVER_TEEHISTORIAN_H
152