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_CLIENT_H |
4 | #define ENGINE_CLIENT_CLIENT_H |
5 | |
6 | #include <deque> |
7 | #include <memory> |
8 | |
9 | #include <base/hash.h> |
10 | |
11 | #include <engine/client.h> |
12 | #include <engine/client/checksum.h> |
13 | #include <engine/client/friends.h> |
14 | #include <engine/client/ghost.h> |
15 | #include <engine/client/serverbrowser.h> |
16 | #include <engine/client/updater.h> |
17 | #include <engine/editor.h> |
18 | #include <engine/graphics.h> |
19 | #include <engine/shared/config.h> |
20 | #include <engine/shared/demo.h> |
21 | #include <engine/shared/fifo.h> |
22 | #include <engine/shared/http.h> |
23 | #include <engine/shared/network.h> |
24 | #include <engine/textrender.h> |
25 | #include <engine/warning.h> |
26 | |
27 | #include "graph.h" |
28 | #include "smooth_time.h" |
29 | |
30 | class CDemoEdit; |
31 | class IDemoRecorder; |
32 | class CMsgPacker; |
33 | class CUnpacker; |
34 | class IConfigManager; |
35 | class IDiscord; |
36 | class IEngine; |
37 | class IEngineInput; |
38 | class IEngineMap; |
39 | class IEngineSound; |
40 | class IFriends; |
41 | class ILogger; |
42 | class ISteam; |
43 | class INotifications; |
44 | class IStorage; |
45 | class IUpdater; |
46 | |
47 | #define CONNECTLINK_DOUBLE_SLASH "ddnet://" |
48 | #define CONNECTLINK_NO_SLASH "ddnet:" |
49 | |
50 | class CServerCapabilities |
51 | { |
52 | public: |
53 | bool m_ChatTimeoutCode = false; |
54 | bool m_AnyPlayerFlag = false; |
55 | bool m_PingEx = false; |
56 | bool m_AllowDummy = false; |
57 | bool m_SyncWeaponInput = false; |
58 | }; |
59 | |
60 | class CClient : public IClient, public CDemoPlayer::IListener |
61 | { |
62 | // needed interfaces |
63 | IConfigManager *m_pConfigManager = nullptr; |
64 | CConfig *m_pConfig = nullptr; |
65 | IConsole *m_pConsole = nullptr; |
66 | IDiscord *m_pDiscord = nullptr; |
67 | IEditor *m_pEditor = nullptr; |
68 | IEngine *m_pEngine = nullptr; |
69 | IFavorites *m_pFavorites = nullptr; |
70 | IGameClient *m_pGameClient = nullptr; |
71 | IEngineGraphics *m_pGraphics = nullptr; |
72 | IEngineInput *m_pInput = nullptr; |
73 | IEngineMap *m_pMap = nullptr; |
74 | IEngineSound *m_pSound = nullptr; |
75 | ISteam *m_pSteam = nullptr; |
76 | INotifications *m_pNotifications = nullptr; |
77 | IStorage *m_pStorage = nullptr; |
78 | IEngineTextRender *m_pTextRender = nullptr; |
79 | IUpdater *m_pUpdater = nullptr; |
80 | CHttp m_Http; |
81 | |
82 | CNetClient m_aNetClient[NUM_CONNS]; |
83 | CDemoPlayer m_DemoPlayer; |
84 | CDemoRecorder m_aDemoRecorder[RECORDER_MAX]; |
85 | CDemoEditor m_DemoEditor; |
86 | CGhostRecorder m_GhostRecorder; |
87 | CGhostLoader m_GhostLoader; |
88 | CServerBrowser m_ServerBrowser; |
89 | CUpdater m_Updater; |
90 | CFriends m_Friends; |
91 | CFriends m_Foes; |
92 | |
93 | char m_aConnectAddressStr[MAX_SERVER_ADDRESSES * NETADDR_MAXSTRSIZE] = "" ; |
94 | |
95 | CUuid m_ConnectionId = UUID_ZEROED; |
96 | |
97 | bool m_HaveGlobalTcpAddr = false; |
98 | NETADDR m_GlobalTcpAddr = NETADDR_ZEROED; |
99 | |
100 | uint64_t m_aSnapshotParts[NUM_DUMMIES] = {0, 0}; |
101 | int64_t m_LocalStartTime = 0; |
102 | int64_t m_GlobalStartTime = 0; |
103 | |
104 | IGraphics::CTextureHandle m_DebugFont; |
105 | |
106 | int64_t m_LastRenderTime; |
107 | |
108 | int m_SnapCrcErrors = 0; |
109 | bool m_AutoScreenshotRecycle = false; |
110 | bool m_AutoStatScreenshotRecycle = false; |
111 | bool m_AutoCSVRecycle = false; |
112 | bool m_EditorActive = false; |
113 | |
114 | int m_aAckGameTick[NUM_DUMMIES] = {-1, -1}; |
115 | int m_aCurrentRecvTick[NUM_DUMMIES] = {0, 0}; |
116 | int m_aRconAuthed[NUM_DUMMIES] = {0, 0}; |
117 | char m_aRconUsername[32] = "" ; |
118 | char m_aRconPassword[sizeof(g_Config.m_SvRconPassword)] = "" ; |
119 | int m_UseTempRconCommands = 0; |
120 | bool m_ReceivingRconCommands = false; |
121 | char m_aPassword[sizeof(g_Config.m_Password)] = "" ; |
122 | bool m_SendPassword = false; |
123 | |
124 | // version-checking |
125 | char m_aVersionStr[10] = "0" ; |
126 | |
127 | // pinging |
128 | int64_t m_PingStartTime = 0; |
129 | |
130 | char m_aCurrentMap[IO_MAX_PATH_LENGTH] = "" ; |
131 | char m_aCurrentMapPath[IO_MAX_PATH_LENGTH] = "" ; |
132 | |
133 | char m_aTimeoutCodes[NUM_DUMMIES][32] = {"" , "" }; |
134 | bool m_aCodeRunAfterJoin[NUM_DUMMIES] = {false, false}; |
135 | bool m_GenerateTimeoutSeed = true; |
136 | |
137 | char m_aCmdConnect[256] = "" ; |
138 | char m_aCmdPlayDemo[IO_MAX_PATH_LENGTH] = "" ; |
139 | char m_aCmdEditMap[IO_MAX_PATH_LENGTH] = "" ; |
140 | |
141 | // map download |
142 | char m_aMapDownloadUrl[256] = "" ; |
143 | std::shared_ptr<CHttpRequest> m_pMapdownloadTask = nullptr; |
144 | char m_aMapdownloadFilename[256] = "" ; |
145 | char m_aMapdownloadFilenameTemp[256] = "" ; |
146 | char m_aMapdownloadName[256] = "" ; |
147 | IOHANDLE m_MapdownloadFileTemp = 0; |
148 | int m_MapdownloadChunk = 0; |
149 | int m_MapdownloadCrc = 0; |
150 | int m_MapdownloadAmount = -1; |
151 | int m_MapdownloadTotalsize = -1; |
152 | bool m_MapdownloadSha256Present = false; |
153 | SHA256_DIGEST m_MapdownloadSha256 = SHA256_ZEROED; |
154 | |
155 | bool m_MapDetailsPresent = false; |
156 | char m_aMapDetailsName[256] = "" ; |
157 | int m_MapDetailsCrc = 0; |
158 | SHA256_DIGEST m_MapDetailsSha256 = SHA256_ZEROED; |
159 | char m_aMapDetailsUrl[256] = "" ; |
160 | |
161 | std::shared_ptr<CHttpRequest> m_pDDNetInfoTask = nullptr; |
162 | |
163 | // time |
164 | CSmoothTime m_aGameTime[NUM_DUMMIES]; |
165 | CSmoothTime m_PredictedTime; |
166 | |
167 | // input |
168 | struct // TODO: handle input better |
169 | { |
170 | int m_aData[MAX_INPUT_SIZE]; // the input data |
171 | int m_Tick; // the tick that the input is for |
172 | int64_t m_PredictedTime; // prediction latency when we sent this input |
173 | int64_t m_PredictionMargin; // prediction margin when we sent this input |
174 | int64_t m_Time; |
175 | } m_aInputs[NUM_DUMMIES][200]; |
176 | |
177 | int m_aCurrentInput[NUM_DUMMIES] = {0, 0}; |
178 | bool m_LastDummy = false; |
179 | bool m_DummySendConnInfo = false; |
180 | bool m_DummyConnected = false; |
181 | int m_LastDummyConnectTime = 0; |
182 | |
183 | // graphs |
184 | CGraph m_InputtimeMarginGraph; |
185 | CGraph m_GametimeMarginGraph; |
186 | CGraph m_FpsGraph; |
187 | |
188 | // the game snapshots are modifiable by the game |
189 | CSnapshotStorage m_aSnapshotStorage[NUM_DUMMIES]; |
190 | CSnapshotStorage::CHolder *m_aapSnapshots[NUM_DUMMIES][NUM_SNAPSHOT_TYPES]; |
191 | |
192 | int m_aReceivedSnapshots[NUM_DUMMIES] = {0, 0}; |
193 | char m_aaSnapshotIncomingData[NUM_DUMMIES][CSnapshot::MAX_SIZE]; |
194 | int m_aSnapshotIncomingDataSize[NUM_DUMMIES] = {0, 0}; |
195 | |
196 | CSnapshotStorage::CHolder m_aDemorecSnapshotHolders[NUM_SNAPSHOT_TYPES]; |
197 | char m_aaaDemorecSnapshotData[NUM_SNAPSHOT_TYPES][2][CSnapshot::MAX_SIZE]; |
198 | |
199 | CSnapshotDelta m_SnapshotDelta; |
200 | |
201 | std::deque<std::shared_ptr<CDemoEdit>> m_EditJobs; |
202 | |
203 | // |
204 | bool m_CanReceiveServerCapabilities = false; |
205 | bool m_ServerSentCapabilities = false; |
206 | CServerCapabilities m_ServerCapabilities; |
207 | |
208 | CServerInfo m_CurrentServerInfo; |
209 | int64_t m_CurrentServerInfoRequestTime = -1; // >= 0 should request, == -1 got info |
210 | |
211 | int m_CurrentServerPingInfoType = -1; |
212 | int m_CurrentServerPingBasicToken = -1; |
213 | int m_CurrentServerPingToken = -1; |
214 | CUuid m_CurrentServerPingUuid = UUID_ZEROED; |
215 | int64_t m_CurrentServerCurrentPingTime = -1; // >= 0 request running |
216 | int64_t m_CurrentServerNextPingTime = -1; // >= 0 should request |
217 | |
218 | // version info |
219 | struct CVersionInfo |
220 | { |
221 | enum |
222 | { |
223 | STATE_INIT = 0, |
224 | STATE_START, |
225 | STATE_READY, |
226 | }; |
227 | |
228 | int m_State = STATE_INIT; |
229 | } m_VersionInfo; |
230 | |
231 | std::vector<SWarning> m_vWarnings; |
232 | std::vector<SWarning> m_vQuittingWarnings; |
233 | |
234 | CFifo m_Fifo; |
235 | |
236 | IOHANDLE m_BenchmarkFile = 0; |
237 | int64_t m_BenchmarkStopTime = 0; |
238 | |
239 | CChecksum m_Checksum; |
240 | int m_OwnExecutableSize = 0; |
241 | IOHANDLE m_OwnExecutable = 0; |
242 | |
243 | // favorite command handling |
244 | bool m_FavoritesGroup = false; |
245 | bool m_FavoritesGroupAllowPing = false; |
246 | int m_FavoritesGroupNum = 0; |
247 | NETADDR m_aFavoritesGroupAddresses[MAX_SERVER_ADDRESSES]; |
248 | |
249 | void UpdateDemoIntraTimers(); |
250 | int MaxLatencyTicks() const; |
251 | int PredictionMargin() const; |
252 | |
253 | std::shared_ptr<ILogger> m_pFileLogger = nullptr; |
254 | std::shared_ptr<ILogger> m_pStdoutLogger = nullptr; |
255 | |
256 | public: |
257 | IConfigManager *ConfigManager() { return m_pConfigManager; } |
258 | CConfig *Config() { return m_pConfig; } |
259 | IDiscord *Discord() { return m_pDiscord; } |
260 | IEngine *Engine() { return m_pEngine; } |
261 | IGameClient *GameClient() { return m_pGameClient; } |
262 | IEngineGraphics *Graphics() { return m_pGraphics; } |
263 | IEngineInput *Input() { return m_pInput; } |
264 | IEngineSound *Sound() { return m_pSound; } |
265 | ISteam *Steam() { return m_pSteam; } |
266 | INotifications *Notifications() { return m_pNotifications; } |
267 | IStorage *Storage() { return m_pStorage; } |
268 | IEngineTextRender *TextRender() { return m_pTextRender; } |
269 | IUpdater *Updater() { return m_pUpdater; } |
270 | IHttp *Http() { return &m_Http; } |
271 | |
272 | CClient(); |
273 | |
274 | // ----- send functions ----- |
275 | int SendMsg(int Conn, CMsgPacker *pMsg, int Flags) override; |
276 | // Send via the currently active client (main/dummy) |
277 | int SendMsgActive(CMsgPacker *pMsg, int Flags) override; |
278 | |
279 | void SendInfo(int Conn); |
280 | void SendEnterGame(int Conn); |
281 | void SendReady(int Conn); |
282 | void SendMapRequest(); |
283 | |
284 | bool RconAuthed() const override { return m_aRconAuthed[g_Config.m_ClDummy] != 0; } |
285 | bool UseTempRconCommands() const override { return m_UseTempRconCommands != 0; } |
286 | void RconAuth(const char *pName, const char *pPassword) override; |
287 | void Rcon(const char *pCmd) override; |
288 | bool ReceivingRconCommands() const override { return m_ReceivingRconCommands; } |
289 | |
290 | bool ConnectionProblems() const override; |
291 | |
292 | IGraphics::CTextureHandle GetDebugFont() const override { return m_DebugFont; } |
293 | |
294 | void DirectInput(int *pInput, int Size); |
295 | void SendInput(); |
296 | |
297 | // TODO: OPT: do this a lot smarter! |
298 | int *GetInput(int Tick, int IsDummy) const override; |
299 | |
300 | const char *LatestVersion() const override; |
301 | |
302 | // ------ state handling ----- |
303 | void SetState(EClientState State); |
304 | |
305 | // called when the map is loaded and we should init for a new round |
306 | void OnEnterGame(bool Dummy); |
307 | void EnterGame(int Conn) override; |
308 | |
309 | void Connect(const char *pAddress, const char *pPassword = nullptr) override; |
310 | void DisconnectWithReason(const char *pReason); |
311 | void Disconnect() override; |
312 | |
313 | void DummyDisconnect(const char *pReason) override; |
314 | void DummyConnect() override; |
315 | bool DummyConnected() const override; |
316 | bool DummyConnecting() const override; |
317 | bool DummyAllowed() const override; |
318 | |
319 | void GetServerInfo(CServerInfo *pServerInfo) const override; |
320 | void ServerInfoRequest(); |
321 | |
322 | void LoadDebugFont(); |
323 | |
324 | // --- |
325 | |
326 | int GetPredictionTime() override; |
327 | void *SnapGetItem(int SnapId, int Index, CSnapItem *pItem) const override; |
328 | int SnapItemSize(int SnapId, int Index) const override; |
329 | const void *SnapFindItem(int SnapId, int Type, int Id) const override; |
330 | int SnapNumItems(int SnapId) const override; |
331 | void SnapSetStaticsize(int ItemType, int Size) override; |
332 | |
333 | void Render(); |
334 | void DebugRender(); |
335 | |
336 | void Restart() override; |
337 | void Quit() override; |
338 | |
339 | const char *PlayerName() const override; |
340 | const char *DummyName() const override; |
341 | const char *ErrorString() const override; |
342 | |
343 | const char *LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc); |
344 | const char *LoadMapSearch(const char *pMapName, SHA256_DIGEST *pWantedSha256, int WantedCrc); |
345 | |
346 | void ProcessConnlessPacket(CNetChunk *pPacket); |
347 | void ProcessServerInfo(int Type, NETADDR *pFrom, const void *pData, int DataSize); |
348 | void ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy); |
349 | |
350 | int UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo); |
351 | |
352 | void ResetMapDownload(); |
353 | void FinishMapDownload(); |
354 | |
355 | void RequestDDNetInfo() override; |
356 | void ResetDDNetInfoTask(); |
357 | void FinishDDNetInfo(); |
358 | void LoadDDNetInfo(); |
359 | |
360 | const NETADDR &ServerAddress() const override { return *m_aNetClient[CONN_MAIN].ServerAddress(); } |
361 | int ConnectNetTypes() const override; |
362 | const char *ConnectAddressString() const override { return m_aConnectAddressStr; } |
363 | const char *MapDownloadName() const override { return m_aMapdownloadName; } |
364 | int MapDownloadAmount() const override { return !m_pMapdownloadTask ? m_MapdownloadAmount : (int)m_pMapdownloadTask->Current(); } |
365 | int MapDownloadTotalsize() const override { return !m_pMapdownloadTask ? m_MapdownloadTotalsize : (int)m_pMapdownloadTask->Size(); } |
366 | |
367 | void PumpNetwork(); |
368 | |
369 | void OnDemoPlayerSnapshot(void *pData, int Size) override; |
370 | void OnDemoPlayerMessage(void *pData, int Size) override; |
371 | |
372 | void Update(); |
373 | |
374 | void RegisterInterfaces(); |
375 | void InitInterfaces(); |
376 | |
377 | void Run(); |
378 | |
379 | bool InitNetworkClient(char *pError, size_t ErrorSize); |
380 | bool CtrlShiftKey(int Key, bool &Last); |
381 | |
382 | static void Con_Connect(IConsole::IResult *pResult, void *pUserData); |
383 | static void Con_Disconnect(IConsole::IResult *pResult, void *pUserData); |
384 | |
385 | static void Con_DummyConnect(IConsole::IResult *pResult, void *pUserData); |
386 | static void Con_DummyDisconnect(IConsole::IResult *pResult, void *pUserData); |
387 | static void Con_DummyResetInput(IConsole::IResult *pResult, void *pUserData); |
388 | |
389 | static void Con_Quit(IConsole::IResult *pResult, void *pUserData); |
390 | static void Con_Restart(IConsole::IResult *pResult, void *pUserData); |
391 | static void Con_DemoPlay(IConsole::IResult *pResult, void *pUserData); |
392 | static void Con_DemoSpeed(IConsole::IResult *pResult, void *pUserData); |
393 | static void Con_Minimize(IConsole::IResult *pResult, void *pUserData); |
394 | static void Con_Ping(IConsole::IResult *pResult, void *pUserData); |
395 | static void Con_Screenshot(IConsole::IResult *pResult, void *pUserData); |
396 | |
397 | #if defined(CONF_VIDEORECORDER) |
398 | void StartVideo(const char *pFilename, bool WithTimestamp); |
399 | static void Con_StartVideo(IConsole::IResult *pResult, void *pUserData); |
400 | static void Con_StopVideo(IConsole::IResult *pResult, void *pUserData); |
401 | const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex, bool StartPaused = false) override; |
402 | #endif |
403 | |
404 | static void Con_Rcon(IConsole::IResult *pResult, void *pUserData); |
405 | static void Con_RconAuth(IConsole::IResult *pResult, void *pUserData); |
406 | static void Con_RconLogin(IConsole::IResult *pResult, void *pUserData); |
407 | static void Con_BeginFavoriteGroup(IConsole::IResult *pResult, void *pUserData); |
408 | static void Con_EndFavoriteGroup(IConsole::IResult *pResult, void *pUserData); |
409 | static void Con_AddFavorite(IConsole::IResult *pResult, void *pUserData); |
410 | static void Con_RemoveFavorite(IConsole::IResult *pResult, void *pUserData); |
411 | static void Con_Play(IConsole::IResult *pResult, void *pUserData); |
412 | static void Con_Record(IConsole::IResult *pResult, void *pUserData); |
413 | static void Con_StopRecord(IConsole::IResult *pResult, void *pUserData); |
414 | static void Con_AddDemoMarker(IConsole::IResult *pResult, void *pUserData); |
415 | static void Con_BenchmarkQuit(IConsole::IResult *pResult, void *pUserData); |
416 | static void ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
417 | static void ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
418 | static void ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
419 | static void ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
420 | static void ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
421 | static void ConchainWindowResize(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
422 | static void ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
423 | static void ConchainPassword(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
424 | static void ConchainReplays(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
425 | static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
426 | static void ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); |
427 | |
428 | static void Con_DemoSlice(IConsole::IResult *pResult, void *pUserData); |
429 | static void Con_DemoSliceBegin(IConsole::IResult *pResult, void *pUserData); |
430 | static void Con_DemoSliceEnd(IConsole::IResult *pResult, void *pUserData); |
431 | static void Con_SaveReplay(IConsole::IResult *pResult, void *pUserData); |
432 | |
433 | void RegisterCommands(); |
434 | |
435 | const char *DemoPlayer_Play(const char *pFilename, int StorageType) override; |
436 | void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) override; |
437 | void DemoRecorder_HandleAutoStart() override; |
438 | void DemoRecorder_UpdateReplayRecorder() override; |
439 | void DemoRecorder_AddDemoMarker(int Recorder); |
440 | IDemoRecorder *DemoRecorder(int Recorder) override; |
441 | |
442 | void AutoScreenshot_Start() override; |
443 | void AutoStatScreenshot_Start() override; |
444 | void AutoScreenshot_Cleanup(); |
445 | void AutoStatScreenshot_Cleanup(); |
446 | |
447 | void AutoCSV_Start() override; |
448 | void AutoCSV_Cleanup(); |
449 | |
450 | void ServerBrowserUpdate() override; |
451 | |
452 | void HandleConnectAddress(const NETADDR *pAddr); |
453 | void HandleConnectLink(const char *pLink); |
454 | void HandleDemoPath(const char *pPath); |
455 | void HandleMapPath(const char *pPath); |
456 | |
457 | virtual void InitChecksum(); |
458 | virtual int HandleChecksum(int Conn, CUuid Uuid, CUnpacker *pUnpacker); |
459 | |
460 | // gfx |
461 | void SwitchWindowScreen(int Index) override; |
462 | void SetWindowParams(int FullscreenMode, bool IsBorderless) override; |
463 | void ToggleWindowVSync() override; |
464 | void Notify(const char *pTitle, const char *pMessage) override; |
465 | void OnWindowResize() override; |
466 | void BenchmarkQuit(int Seconds, const char *pFilename); |
467 | |
468 | void UpdateAndSwap() override; |
469 | |
470 | // DDRace |
471 | |
472 | void GenerateTimeoutSeed() override; |
473 | void GenerateTimeoutCodes(const NETADDR *pAddrs, int NumAddrs); |
474 | |
475 | int GetCurrentRaceTime() override; |
476 | |
477 | const char *GetCurrentMap() const override; |
478 | const char *GetCurrentMapPath() const override; |
479 | SHA256_DIGEST GetCurrentMapSha256() const override; |
480 | unsigned GetCurrentMapCrc() const override; |
481 | |
482 | void RaceRecord_Start(const char *pFilename) override; |
483 | void RaceRecord_Stop() override; |
484 | bool RaceRecord_IsRecording() override; |
485 | |
486 | void DemoSliceBegin() override; |
487 | void DemoSliceEnd() override; |
488 | void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) override; |
489 | virtual void SaveReplay(int Length, const char *pFilename = "" ); |
490 | |
491 | bool EditorHasUnsavedData() const override { return m_pEditor->HasUnsavedData(); } |
492 | |
493 | IFriends *Foes() override { return &m_Foes; } |
494 | |
495 | void GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount) override; |
496 | |
497 | void AddWarning(const SWarning &Warning) override; |
498 | SWarning *GetCurWarning() override; |
499 | std::vector<SWarning> &&QuittingWarnings() { return std::move(m_vQuittingWarnings); } |
500 | |
501 | CChecksumData *ChecksumData() override { return &m_Checksum.m_Data; } |
502 | int UdpConnectivity(int NetType) override; |
503 | |
504 | #if defined(CONF_FAMILY_WINDOWS) |
505 | void ShellRegister() override; |
506 | void ShellUnregister() override; |
507 | #endif |
508 | |
509 | void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) override; |
510 | void GetGpuInfoString(char (&aGpuInfo)[256]) override; |
511 | void SetLoggers(std::shared_ptr<ILogger> &&pFileLogger, std::shared_ptr<ILogger> &&pStdoutLogger); |
512 | }; |
513 | |
514 | #endif |
515 | |