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