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 | |
16 | struct SWarning; |
17 | |
18 | enum |
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 | |
29 | typedef bool (*CLIENTFUNC_FILTER)(const void *pData, int DataSize, void *pUser); |
30 | struct CChecksumData; |
31 | |
32 | class IClient : public IInterface |
33 | { |
34 | MACRO_INTERFACE("client" ) |
35 | public: |
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 | |
70 | protected: |
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 | |
97 | public: |
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 | |
299 | class IGameClient : public IInterface |
300 | { |
301 | MACRO_INTERFACE("gameclient" ) |
302 | protected: |
303 | public: |
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 | |
343 | void (unsigned char *pData); |
344 | |
345 | extern IGameClient *CreateGameClient(); |
346 | #endif |
347 | |