1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_CLIENT_H
4#define ENGINE_CLIENT_H
5#include "kernel.h"
6
7#include "graphics.h"
8#include "message.h"
9#include <base/hash.h>
10
11#include <game/generated/protocol.h>
12
13#include <engine/friends.h>
14#include <functional>
15
16struct SWarning;
17
18enum
19{
20 RECORDER_MANUAL = 0,
21 RECORDER_AUTO = 1,
22 RECORDER_RACE = 2,
23 RECORDER_REPLAYS = 3,
24 RECORDER_MAX = 4,
25
26 NUM_DUMMIES = 2,
27};
28
29typedef bool (*CLIENTFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
30struct CChecksumData;
31
32class IClient : public IInterface
33{
34 MACRO_INTERFACE("client")
35public:
36 /* Constants: Client States
37 STATE_OFFLINE - The client is offline.
38 STATE_CONNECTING - The client is trying to connect to a server.
39 STATE_LOADING - The client has connected to a server and is loading resources.
40 STATE_ONLINE - The client is connected to a server and running the game.
41 STATE_DEMOPLAYBACK - The client is playing a demo
42 STATE_QUITTING - The client is quitting.
43 */
44
45 enum EClientState
46 {
47 STATE_OFFLINE = 0,
48 STATE_CONNECTING,
49 STATE_LOADING,
50 STATE_ONLINE,
51 STATE_DEMOPLAYBACK,
52 STATE_QUITTING,
53 STATE_RESTARTING,
54 };
55
56 /**
57 * More precise state for @see STATE_LOADING
58 * Sets what is actually happening in the client right now
59 */
60 enum ELoadingStateDetail
61 {
62 LOADING_STATE_DETAIL_INITIAL,
63 LOADING_STATE_DETAIL_LOADING_MAP,
64 LOADING_STATE_DETAIL_SENDING_READY,
65 LOADING_STATE_DETAIL_GETTING_READY,
66 };
67
68 typedef std::function<void()> TMapLoadingCallbackFunc;
69
70protected:
71 // quick access to state of the client
72 EClientState m_State = IClient::STATE_OFFLINE;
73 ELoadingStateDetail m_LoadingStateDetail = LOADING_STATE_DETAIL_INITIAL;
74 int64_t m_StateStartTime;
75
76 // quick access to time variables
77 int m_aPrevGameTick[NUM_DUMMIES] = {0, 0};
78 int m_aCurGameTick[NUM_DUMMIES] = {0, 0};
79 float m_aGameIntraTick[NUM_DUMMIES] = {0.0f, 0.0f};
80 float m_aGameTickTime[NUM_DUMMIES] = {0.0f, 0.0f};
81 float m_aGameIntraTickSincePrev[NUM_DUMMIES] = {0.0f, 0.0f};
82
83 int m_aPredTick[NUM_DUMMIES] = {0, 0};
84 float m_aPredIntraTick[NUM_DUMMIES] = {0.0f, 0.0f};
85
86 float m_LocalTime = 0.0f;
87 float m_GlobalTime = 0.0f;
88 float m_RenderFrameTime = 0.0001f;
89 float m_FrameTimeAvg = 0.0001f;
90
91 TMapLoadingCallbackFunc m_MapLoadingCBFunc = nullptr;
92
93 char m_aNews[3000] = "";
94 int m_Points = -1;
95 int64_t m_ReconnectTime = 0;
96
97public:
98 class CSnapItem
99 {
100 public:
101 int m_Type;
102 int m_Id;
103 int m_DataSize;
104 };
105
106 enum
107 {
108 CONN_MAIN = 0,
109 CONN_DUMMY,
110 CONN_CONTACT,
111 NUM_CONNS,
112 };
113
114 enum
115 {
116 CONNECTIVITY_UNKNOWN,
117 CONNECTIVITY_CHECKING,
118 CONNECTIVITY_UNREACHABLE,
119 CONNECTIVITY_REACHABLE,
120 // Different global IP address has been detected for UDP and
121 // TCP connections.
122 CONNECTIVITY_DIFFERING_UDP_TCP_IP_ADDRESSES,
123 };
124
125 //
126 inline EClientState State() const { return m_State; }
127 inline ELoadingStateDetail LoadingStateDetail() const { return m_LoadingStateDetail; }
128 inline int64_t StateStartTime() const { return m_StateStartTime; }
129 void SetLoadingStateDetail(ELoadingStateDetail LoadingStateDetail) { m_LoadingStateDetail = LoadingStateDetail; }
130
131 void SetMapLoadingCBFunc(TMapLoadingCallbackFunc &&Func) { m_MapLoadingCBFunc = std::move(Func); }
132
133 // tick time access
134 inline int PrevGameTick(int Conn) const { return m_aPrevGameTick[Conn]; }
135 inline int GameTick(int Conn) const { return m_aCurGameTick[Conn]; }
136 inline int PredGameTick(int Conn) const { return m_aPredTick[Conn]; }
137 inline float IntraGameTick(int Conn) const { return m_aGameIntraTick[Conn]; }
138 inline float PredIntraGameTick(int Conn) const { return m_aPredIntraTick[Conn]; }
139 inline float IntraGameTickSincePrev(int Conn) const { return m_aGameIntraTickSincePrev[Conn]; }
140 inline float GameTickTime(int Conn) const { return m_aGameTickTime[Conn]; }
141 inline int GameTickSpeed() const { return SERVER_TICK_SPEED; }
142
143 // other time access
144 inline float RenderFrameTime() const { return m_RenderFrameTime; }
145 inline float LocalTime() const { return m_LocalTime; }
146 inline float GlobalTime() const { return m_GlobalTime; }
147 inline float FrameTimeAvg() const { return m_FrameTimeAvg; }
148
149 // actions
150 virtual void Connect(const char *pAddress, const char *pPassword = nullptr) = 0;
151 virtual void Disconnect() = 0;
152
153 // dummy
154 virtual void DummyDisconnect(const char *pReason) = 0;
155 virtual void DummyConnect() = 0;
156 virtual bool DummyConnected() = 0;
157 virtual bool DummyConnecting() = 0;
158 virtual bool DummyAllowed() = 0;
159
160 virtual void Restart() = 0;
161 virtual void Quit() = 0;
162 virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0;
163#if defined(CONF_VIDEORECORDER)
164 virtual const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex, bool StartPaused = false) = 0;
165#endif
166 virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) = 0;
167 virtual void DemoRecorder_HandleAutoStart() = 0;
168 virtual void DemoRecorder_UpdateReplayRecorder() = 0;
169 virtual class IDemoRecorder *DemoRecorder(int Recorder) = 0;
170 virtual void AutoScreenshot_Start() = 0;
171 virtual void AutoStatScreenshot_Start() = 0;
172 virtual void AutoCSV_Start() = 0;
173 virtual void ServerBrowserUpdate() = 0;
174
175 // gfx
176 virtual void SwitchWindowScreen(int Index) = 0;
177 virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
178 virtual void ToggleWindowVSync() = 0;
179 virtual void Notify(const char *pTitle, const char *pMessage) = 0;
180 virtual void OnWindowResize() = 0;
181
182 virtual void UpdateAndSwap() = 0;
183
184 // networking
185 virtual void EnterGame(int Conn) = 0;
186
187 //
188 virtual const NETADDR &ServerAddress() const = 0;
189 virtual int ConnectNetTypes() const = 0;
190 virtual const char *ConnectAddressString() const = 0;
191 virtual const char *MapDownloadName() const = 0;
192 virtual int MapDownloadAmount() const = 0;
193 virtual int MapDownloadTotalsize() const = 0;
194
195 // input
196 virtual int *GetInput(int Tick, int IsDummy = 0) const = 0;
197
198 // remote console
199 virtual void RconAuth(const char *pUsername, const char *pPassword) = 0;
200 virtual bool RconAuthed() const = 0;
201 virtual bool UseTempRconCommands() const = 0;
202 virtual void Rcon(const char *pLine) = 0;
203 virtual bool ReceivingRconCommands() const = 0;
204
205 // server info
206 virtual void GetServerInfo(class CServerInfo *pServerInfo) const = 0;
207
208 virtual int GetPredictionTime() = 0;
209
210 // snapshot interface
211
212 enum
213 {
214 SNAP_CURRENT = 0,
215 SNAP_PREV = 1,
216 NUM_SNAPSHOT_TYPES = 2,
217 };
218
219 // TODO: Refactor: should redo this a bit i think, too many virtual calls
220 virtual int SnapNumItems(int SnapId) const = 0;
221 virtual const void *SnapFindItem(int SnapId, int Type, int Id) const = 0;
222 virtual void *SnapGetItem(int SnapId, int Index, CSnapItem *pItem) const = 0;
223 virtual int SnapItemSize(int SnapId, int Index) const = 0;
224
225 virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
226
227 virtual int SendMsg(int Conn, CMsgPacker *pMsg, int Flags) = 0;
228 virtual int SendMsgActive(CMsgPacker *pMsg, int Flags) = 0;
229
230 template<class T>
231 int SendPackMsgActive(T *pMsg, int Flags)
232 {
233 CMsgPacker Packer(T::ms_MsgId, false);
234 if(pMsg->Pack(&Packer))
235 return -1;
236 return SendMsgActive(pMsg: &Packer, Flags);
237 }
238
239 //
240 virtual const char *PlayerName() const = 0;
241 virtual const char *DummyName() const = 0;
242 virtual const char *ErrorString() const = 0;
243 virtual const char *LatestVersion() const = 0;
244 virtual bool ConnectionProblems() const = 0;
245
246 virtual IGraphics::CTextureHandle GetDebugFont() const = 0; // TODO: remove this function
247
248 //DDRace
249
250 virtual const char *GetCurrentMap() const = 0;
251 virtual const char *GetCurrentMapPath() const = 0;
252 virtual SHA256_DIGEST GetCurrentMapSha256() const = 0;
253 virtual unsigned GetCurrentMapCrc() const = 0;
254
255 const char *News() const { return m_aNews; }
256 int Points() const { return m_Points; }
257 int64_t ReconnectTime() const { return m_ReconnectTime; }
258 void SetReconnectTime(int64_t ReconnectTime) { m_ReconnectTime = ReconnectTime; }
259 virtual int GetCurrentRaceTime() = 0;
260
261 virtual void RaceRecord_Start(const char *pFilename) = 0;
262 virtual void RaceRecord_Stop() = 0;
263 virtual bool RaceRecord_IsRecording() = 0;
264
265 virtual void DemoSliceBegin() = 0;
266 virtual void DemoSliceEnd() = 0;
267 virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) = 0;
268
269 virtual void RequestDDNetInfo() = 0;
270 virtual bool EditorHasUnsavedData() const = 0;
271
272 virtual void GenerateTimeoutSeed() = 0;
273
274 virtual IFriends *Foes() = 0;
275
276 virtual void GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount) = 0;
277
278 virtual void AddWarning(const SWarning &Warning) = 0;
279 virtual SWarning *GetCurWarning() = 0;
280
281 virtual CChecksumData *ChecksumData() = 0;
282 virtual int UdpConnectivity(int NetType) = 0;
283
284#if defined(CONF_FAMILY_WINDOWS)
285 virtual void ShellRegister() = 0;
286 virtual void ShellUnregister() = 0;
287#endif
288
289 enum EMessageBoxType
290 {
291 MESSAGE_BOX_TYPE_ERROR,
292 MESSAGE_BOX_TYPE_WARNING,
293 MESSAGE_BOX_TYPE_INFO,
294 };
295 virtual void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) = 0;
296 virtual void GetGpuInfoString(char (&aGpuInfo)[256]) = 0;
297};
298
299class IGameClient : public IInterface
300{
301 MACRO_INTERFACE("gameclient")
302protected:
303public:
304 virtual void OnConsoleInit() = 0;
305
306 virtual void OnRconType(bool UsernameReq) = 0;
307 virtual void OnRconLine(const char *pLine) = 0;
308 virtual void OnInit() = 0;
309 virtual void InvalidateSnapshot() = 0;
310 virtual void OnNewSnapshot() = 0;
311 virtual void OnEnterGame() = 0;
312 virtual void OnShutdown() = 0;
313 virtual void OnRender() = 0;
314 virtual void OnUpdate() = 0;
315 virtual void OnStateChange(int NewState, int OldState) = 0;
316 virtual void OnConnected() = 0;
317 virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, int Conn, bool Dummy) = 0;
318 virtual void OnPredict() = 0;
319 virtual void OnActivateEditor() = 0;
320 virtual void OnWindowResize() = 0;
321
322 virtual int OnSnapInput(int *pData, bool Dummy, bool Force) = 0;
323 virtual void OnDummySwap() = 0;
324 virtual void SendDummyInfo(bool Start) = 0;
325 virtual int GetLastRaceTick() const = 0;
326
327 virtual const char *GetItemName(int Type) const = 0;
328 virtual const char *Version() const = 0;
329 virtual const char *NetVersion() const = 0;
330 virtual int DDNetVersion() const = 0;
331 virtual const char *DDNetVersionStr() const = 0;
332
333 virtual void OnDummyDisconnect() = 0;
334 virtual void DummyResetInput() = 0;
335 virtual void Echo(const char *pString) = 0;
336
337 virtual bool CanDisplayWarning() const = 0;
338 virtual void RenderShutdownMessage() = 0;
339
340 virtual CNetObjHandler *GetNetObjHandler() = 0;
341};
342
343void SnapshotRemoveExtraProjectileInfo(unsigned char *pData);
344
345extern IGameClient *CreateGameClient();
346#endif
347