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