1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: steam.cpp
5 Desc: various callback functions for steam
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "main.hpp"
13 #include "game.hpp"
14 #include "stat.hpp"
15 #include "net.hpp"
16 #include "menu.hpp"
17 #include "monster.hpp"
18 #include "scores.hpp"
19 #include "entity.hpp"
20 #include "items.hpp"
21 #include "interface/interface.hpp"
22 #include <SDL_thread.h>
23 #include "player.hpp"
24 #include "mod_tools.hpp"
25 #include "interface/ui.hpp"
26 #ifdef STEAMWORKS
27 #include <steam/steam_api.h>
28 #include <steam/steam_gameserver.h>
29 #include "steam.hpp"
30 #include "lobbies.hpp"
31 #endif
32
33 #ifdef STEAMWORKS
34
35 Uint32 numSteamLobbies = 0;
36 int selectedSteamLobby = 0;
37 char lobbyText[MAX_STEAM_LOBBIES][64];
38 void* lobbyIDs[MAX_STEAM_LOBBIES] = { NULL };
39 int lobbyPlayers[MAX_STEAM_LOBBIES] = { 0 };
40
41 void* steamIDRemote[MAXPLAYERS] = {NULL, NULL, NULL, NULL};
42
43 char currentLobbyName[32] = { 0 };
44 Uint32 currentSvFlags = 0;
45 #ifdef STEAMWORKS
46 ELobbyType currentLobbyType = k_ELobbyTypePrivate;
47 #endif
48 bool stillConnectingToLobby = false;
49
50 bool serverLoadingSaveGame = false; // determines whether lobbyToConnectTo is loading a savegame or not
51 void* currentLobby = NULL; // CSteamID to the current game lobby
52 void* lobbyToConnectTo = NULL; // CSteamID of the game lobby that user has been invited to
53 void* steamIDGameServer = NULL; // CSteamID to the current game server
54 uint32_t steamServerIP = 0; // ipv4 address for the current game server
55 uint16_t steamServerPort = 0; // port number for the current game server
56 char pchCmdLine[1024] = { 0 }; // for game join requests
57
58 // menu stuff
59 bool connectingToLobby = false, connectingToLobbyWindow = false;
60 bool requestingLobbies = false;
61 bool joinLobbyWaitingForHostResponse = false;
62 bool denyLobbyJoinEvent = false;
63 int connectingToLobbyStatus = EResult::k_EResultOK;
64
65 const std::string CSteamLeaderboards::leaderboardNames[CSteamLeaderboards::k_numLeaderboards] =
66 {
67 "None",
68
69 "Fastest Time (Normal)",
70 "Highest Score (Normal)",
71
72 "Fastest Time (Multiplayer)",
73 "Highest Score (Multiplayer)",
74
75 "Fastest Time (Hell Route)",
76 "Highest Score (Hell Route)",
77
78 "Fastest Time (Hardcore)",
79 "Highest Score (Hardcore)",
80
81 "Fastest Time (Classic)",
82 "Highest Score (Classic)",
83
84 "Fastest Time (Classic Hardcore)",
85 "Highest Score (Classic Hardcore)",
86
87 "Fastest Time (Multiplayer Classic)",
88 "Highest Score (Multiplayer Classic)",
89
90 "Fastest Time (Multiplayer Hell Route)",
91 "Highest Score (Multiplayer Hell Route)",
92
93 "Fastest Time (Normal - Monsters Only)",
94 "Highest Score (Normal - Monsters Only)",
95
96 "Fastest Time (Multiplayer - Monsters Only)",
97 "Highest Score (Multiplayer - Monsters Only)",
98
99 "Fastest Time (Hell Route - Monsters Only)",
100 "Highest Score (Hell Route - Monsters Only)",
101
102 "Fastest Time (Hardcore - Monsters Only)",
103 "Highest Score (Hardcore - Monsters Only)",
104
105 "Fastest Time (Classic - Monsters Only)",
106 "Highest Score (Classic - Monsters Only)",
107
108 "Fastest Time (Classic Hardcore - Monsters Only)",
109 "Highest Score (Classic Hardcore - Monsters Only)",
110
111 "Fastest Time (Multiplayer Classic - Monsters Only)",
112 "Highest Score (Multiplayer Classic - Monsters Only)",
113
114 "Fastest Time (Multiplayer Hell Route - Monsters Only)",
115 "Highest Score (Multiplayer Hell Route - Monsters Only)"
116 };
117 #endif
118
119
120
121
122
123
124 /* ***** BEGIN UTTER BODGE ***** */
125
126 //These are all an utter bodge. They really, really should not exist, but potato.
127
128
129 #ifdef STEAMWORKS
130 //TODO: Unused?
131 void (*cpp_SteamServerClientWrapper_GameServerPingOnServerResponded)(void* steamID);
132 void (*cpp_SteamServerClientWrapper_OnLobbyDataUpdate)(void* pCallback);
133 void (*cpp_SteamServerClientWrapper_OnSteamShutdown)(void* callback);
134 void (*cpp_SteamServerClientWrapper_OnIPCFailure)(void* failure);
135 void (*cpp_SteamServerClientWrapper_OnP2PSessionRequest)(void* pCallback);
136 void (*cpp_SteamServerClientWrapper_OnP2PSessionConnectFail)(void* pCallback);
137 void (*cpp_SteamServerClientWrapper_OnWorkshopItemInstalled)(void* pParam);
138 void (*cpp_SteamServerClientWrapper_OnGameWebCallback)(void* callback);
139 //void (*cpp_SteamServerClientWrapper_OnGameOverlayActivated)(void *callback);
140 void (*cpp_SteamServerClientWrapper_OnSteamServerConnectFailure)(void* callback);
141 void (*cpp_SteamServerClientWrapper_OnSteamServersDisconnected)(void* callback);
142 void (*cpp_SteamServerClientWrapper_OnSteamServersConnected)(void* callback);
143 void (*cpp_SteamServerClientWrapper_OnAvatarImageLoaded)(void* pCallback);
144 void (*cpp_SteamServerClientWrapper_OnGameJoinRequested)(void* pCallback);
145 void (*cpp_SteamServerClientWrapper_OnLobbyGameCreated)(void* pCallback);
146 void (*cpp_SteamServerClientWrapper_OnLobbyEntered)(void* pCallback, bool bIOFailure); //Where pCallback is a pointer to type LobbyEnter_t.
147 void (*cpp_SteamServerClientWrapper_OnLobbyMatchListCallback)(void* pCallback, bool bIOFailure); //Where pCallback is a pointer to type LobbyMatchList_t.
148 void (*cpp_SteamServerClientWrapper_OnLobbyCreated)(void* pCallback, bool bIOFailure); //Where pCallback is a pointer to type LobbyCreated_t.
149
150 void (*cpp_SteamServerWrapper_OnValidateAuthTicketResponse)(void* pResponse);
151 void (*cpp_SteamServerWrapper_OnPolicyResponse)(void* pPolicyResponse);
152 void (*cpp_SteamServerWrapper_OnP2PSessionConnectFail)(void* pCallback);
153 void (*cpp_SteamServerWrapper_OnP2PSessionRequest)(void* p_Callback);
154 void (*cpp_SteamServerWrapper_OnSteamServersConnectFailure)(void* pConnectFailure);
155 void (*cpp_SteamServerWrapper_OnSteamServersDisconnected)(void* pLoggedOff);
156 void (*cpp_SteamServerWrapper_OnSteamServersConnected)(void* pLogonSuccess);
157 void (*cpp_SteamServerClientWrapper_OnRequestEncryptedAppTicket)(void* pEncryptedAppTicketResponse, bool bIOFailure); //Where pEncryptedAppTicketResponse is of type
158
159
160
161 class SteamServerWrapper
162 {
163 public:
SteamServerWrapper()164 SteamServerWrapper()
165 :
166 m_CallbackSteamServersConnected(this, &SteamServerWrapper::OnSteamServersConnected),
167 m_CallbackSteamServersDisconnected(this, &SteamServerWrapper::OnSteamServersDisconnected),
168 m_CallbackSteamServersConnectFailure( this, &SteamServerWrapper::OnSteamServersConnectFailure ),
169 m_CallbackPolicyResponse(this, &SteamServerWrapper::OnPolicyResponse),
170 m_CallbackGSAuthTicketResponse(this, &SteamServerWrapper::OnValidateAuthTicketResponse),
171 m_CallbackP2PSessionRequest(this, &SteamServerWrapper::OnP2PSessionRequest),
172 m_CallbackP2PSessionConnectFail(this, &SteamServerWrapper::OnP2PSessionConnectFail)
173 {
174 cpp_SteamServerWrapper_OnSteamServersConnected = nullptr;
175 cpp_SteamServerWrapper_OnSteamServersDisconnected = nullptr;
176 cpp_SteamServerWrapper_OnSteamServersConnectFailure = nullptr;
177 cpp_SteamServerWrapper_OnP2PSessionRequest = nullptr;
178 cpp_SteamServerWrapper_OnP2PSessionConnectFail = nullptr;
179 cpp_SteamServerWrapper_OnPolicyResponse = nullptr;
180 cpp_SteamServerWrapper_OnValidateAuthTicketResponse = nullptr;
181 }
182
183 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnSteamServersConnected, SteamServersConnected_t, m_CallbackSteamServersConnected);
184
185 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnSteamServersDisconnected, SteamServersDisconnected_t, m_CallbackSteamServersDisconnected);
186
187 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnSteamServersConnectFailure, SteamServerConnectFailure_t, m_CallbackSteamServersConnectFailure);
188
189 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnPolicyResponse, GSPolicyResponse_t, m_CallbackPolicyResponse);
190
191 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnValidateAuthTicketResponse, ValidateAuthTicketResponse_t, m_CallbackGSAuthTicketResponse);
192
193 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnP2PSessionRequest, P2PSessionRequest_t, m_CallbackP2PSessionRequest);
194
195 STEAM_GAMESERVER_CALLBACK(SteamServerWrapper, OnP2PSessionConnectFail, P2PSessionConnectFail_t, m_CallbackP2PSessionConnectFail);
196 }* steam_server_wrapper;
197
OnSteamServersConnected(SteamServersConnected_t * pLogonSuccess)198 void SteamServerWrapper::OnSteamServersConnected(SteamServersConnected_t* pLogonSuccess)
199 {
200 if (cpp_SteamServerWrapper_OnSteamServersConnected)
201 {
202 (*cpp_SteamServerWrapper_OnSteamServersConnected)(pLogonSuccess);
203 }
204 }
205
OnSteamServersDisconnected(SteamServersDisconnected_t * pLoggedOff)206 void SteamServerWrapper::OnSteamServersDisconnected(SteamServersDisconnected_t* pLoggedOff)
207 {
208 if (cpp_SteamServerWrapper_OnSteamServersDisconnected)
209 {
210 (*cpp_SteamServerWrapper_OnSteamServersDisconnected)(pLoggedOff);
211 }
212 }
213
OnSteamServersConnectFailure(SteamServerConnectFailure_t * pConnectFailure)214 void SteamServerWrapper::OnSteamServersConnectFailure(SteamServerConnectFailure_t* pConnectFailure)
215 {
216 if (cpp_SteamServerWrapper_OnSteamServersConnectFailure)
217 {
218 (*cpp_SteamServerWrapper_OnSteamServersConnectFailure)(pConnectFailure);
219 }
220 }
221
OnPolicyResponse(GSPolicyResponse_t * pPolicyResponse)222 void SteamServerWrapper::OnPolicyResponse(GSPolicyResponse_t* pPolicyResponse)
223 {
224 if (cpp_SteamServerWrapper_OnPolicyResponse)
225 {
226 (*cpp_SteamServerWrapper_OnPolicyResponse)(pPolicyResponse);
227 }
228 }
229
OnValidateAuthTicketResponse(ValidateAuthTicketResponse_t * pResponse)230 void SteamServerWrapper::OnValidateAuthTicketResponse(ValidateAuthTicketResponse_t* pResponse)
231 {
232 if (cpp_SteamServerWrapper_OnValidateAuthTicketResponse)
233 {
234 (*cpp_SteamServerWrapper_OnValidateAuthTicketResponse)(pResponse);
235 }
236 }
237
OnP2PSessionRequest(P2PSessionRequest_t * pCallback)238 void SteamServerWrapper::OnP2PSessionRequest(P2PSessionRequest_t* pCallback)
239 {
240 if (cpp_SteamServerWrapper_OnP2PSessionRequest)
241 {
242 (*cpp_SteamServerWrapper_OnP2PSessionRequest)(pCallback);
243 }
244 }
245
OnP2PSessionConnectFail(P2PSessionConnectFail_t * pCallback)246 void SteamServerWrapper::OnP2PSessionConnectFail(P2PSessionConnectFail_t* pCallback)
247 {
248 if (cpp_SteamServerWrapper_OnP2PSessionConnectFail)
249 {
250 (*cpp_SteamServerWrapper_OnP2PSessionConnectFail)(pCallback);
251 }
252 }
253
cpp_SteamServerWrapper_Instantiate()254 void cpp_SteamServerWrapper_Instantiate()
255 {
256 steam_server_wrapper = new SteamServerWrapper();
257 }
258
cpp_SteamServerWrapper_Destroy()259 void cpp_SteamServerWrapper_Destroy()
260 {
261 delete steam_server_wrapper;
262 steam_server_wrapper = nullptr;
263 }
264
265
266
267
268 class SteamServerClientWrapper
269 {
270 public:
SteamServerClientWrapper()271 SteamServerClientWrapper()
272 :
273 m_LobbyGameCreated(this, &SteamServerClientWrapper::OnLobbyGameCreated),
274 m_GameJoinRequested(this, &SteamServerClientWrapper::OnGameJoinRequested),
275 m_AvatarImageLoadedCreated(this, &SteamServerClientWrapper::OnAvatarImageLoaded),
276 m_SteamServersConnected(this, &SteamServerClientWrapper::OnSteamServersConnected),
277 m_SteamServersDisconnected(this, &SteamServerClientWrapper::OnSteamServersDisconnected),
278 m_SteamServerConnectFailure(this, &SteamServerClientWrapper::OnSteamServerConnectFailure),
279 m_CallbackGameOverlayActivated(this, &SteamServerClientWrapper::OnGameOverlayActivated),
280 m_CallbackGameWebCallback( this, &SteamServerClientWrapper::OnGameWebCallback),
281 m_CallbackWorkshopItemInstalled(this, &SteamServerClientWrapper::OnWorkshopItemInstalled),
282 m_CallbackP2PSessionConnectFail(this, &SteamServerClientWrapper::OnP2PSessionConnectFail),
283 m_CallbackP2PSessionRequest(this, &SteamServerClientWrapper::OnP2PSessionRequest),
284 m_CallbackLobbyDataUpdate(this, &SteamServerClientWrapper::OnLobbyDataUpdate),
285 m_IPCFailureCallback(this, &SteamServerClientWrapper::OnIPCFailure),
286 m_SteamShutdownCallback(this, &SteamServerClientWrapper::OnSteamShutdown),
287 m_CallbackLobbyMemberUpdate(this, &SteamServerClientWrapper::OnLobbyMemberUpdate)
288 {
289 cpp_SteamServerClientWrapper_OnLobbyGameCreated = nullptr;
290 cpp_SteamServerClientWrapper_OnGameJoinRequested = nullptr;
291 cpp_SteamServerClientWrapper_OnAvatarImageLoaded = nullptr;
292 cpp_SteamServerClientWrapper_OnSteamServersConnected = nullptr;
293 cpp_SteamServerClientWrapper_OnSteamServersDisconnected = nullptr;
294 cpp_SteamServerClientWrapper_OnSteamServerConnectFailure = nullptr;
295 //cpp_SteamServerClientWrapper_OnGameOverlayActivated = nullptr;
296 cpp_SteamServerClientWrapper_OnGameWebCallback = nullptr;
297 cpp_SteamServerClientWrapper_OnWorkshopItemInstalled = nullptr;
298 cpp_SteamServerClientWrapper_OnP2PSessionConnectFail = nullptr;
299 cpp_SteamServerClientWrapper_OnP2PSessionRequest = nullptr;
300 cpp_SteamServerClientWrapper_OnIPCFailure = nullptr;
301 cpp_SteamServerClientWrapper_OnSteamShutdown = nullptr;
302 cpp_SteamServerClientWrapper_OnLobbyDataUpdate = nullptr;
303 }
304
305 STEAM_CALLBACK(SteamServerClientWrapper, OnLobbyDataUpdate, LobbyDataUpdate_t, m_CallbackLobbyDataUpdate);
306 STEAM_CALLBACK(SteamServerClientWrapper, OnLobbyMemberUpdate, LobbyChatUpdate_t, m_CallbackLobbyMemberUpdate);
307
308 STEAM_CALLBACK(SteamServerClientWrapper, OnLobbyGameCreated, LobbyGameCreated_t, m_LobbyGameCreated);
309
310 STEAM_CALLBACK(SteamServerClientWrapper, OnGameJoinRequested, GameLobbyJoinRequested_t, m_GameJoinRequested);
311
312 //STEAM_CALLBACK( CSpaceWarClient, OnAvatarImageLoaded, AvatarImageLoaded_t, m_AvatarImageLoadedCreated );
313 STEAM_CALLBACK(SteamServerClientWrapper, OnAvatarImageLoaded, AvatarImageLoaded_t, m_AvatarImageLoadedCreated); //TODO: Finish.
314
315 STEAM_CALLBACK(SteamServerClientWrapper, OnSteamServersConnected, SteamServersConnected_t, m_SteamServersConnected);
316
317 STEAM_CALLBACK(SteamServerClientWrapper, OnSteamServersDisconnected, SteamServersDisconnected_t, m_SteamServersDisconnected);
318
319 STEAM_CALLBACK(SteamServerClientWrapper, OnSteamServerConnectFailure, SteamServerConnectFailure_t, m_SteamServerConnectFailure);
320
321 STEAM_CALLBACK(SteamServerClientWrapper, OnGameOverlayActivated, GameOverlayActivated_t, m_CallbackGameOverlayActivated);
322
323 //STEAM_CALLBACK( CSpaceWarClient, OnGameWebCallback, GameWebCallback_t, m_CallbackGameWebCallback );
324 STEAM_CALLBACK(SteamServerClientWrapper, OnGameWebCallback, GameWebCallback_t, m_CallbackGameWebCallback); //TODO: Finish.
325
326 //STEAM_CALLBACK(CSpaceWarClient, OnWorkshopItemInstalled, ItemInstalled_t, m_CallbackWorkshopItemInstalled);
327 STEAM_CALLBACK(SteamServerClientWrapper, OnWorkshopItemInstalled, ItemInstalled_t, m_CallbackWorkshopItemInstalled); //TODO: Finish.
328
329 STEAM_CALLBACK(SteamServerClientWrapper, OnP2PSessionConnectFail, P2PSessionConnectFail_t, m_CallbackP2PSessionConnectFail);
330
331 STEAM_CALLBACK(SteamServerClientWrapper, OnIPCFailure, IPCFailure_t, m_IPCFailureCallback);
332
333 STEAM_CALLBACK(SteamServerClientWrapper, OnSteamShutdown, SteamShutdown_t, m_SteamShutdownCallback);
334
335 STEAM_CALLBACK(SteamServerClientWrapper, OnP2PSessionRequest, P2PSessionRequest_t, m_CallbackP2PSessionRequest);
336
337 void OnLobbyCreated(LobbyCreated_t* pCallback, bool bIOFailure);
338 CCallResult<SteamServerClientWrapper, LobbyCreated_t> m_SteamCallResultLobbyCreated;
339 void m_SteamCallResultLobbyCreated_Set(SteamAPICall_t hSteamAPICall);
340
341 void OnLobbyEntered( LobbyEnter_t* pCallback, bool bIOFailure );
342 CCallResult<SteamServerClientWrapper, LobbyEnter_t> m_SteamCallResultLobbyEntered; //Why isn't this set in the example?
343 void m_SteamCallResultLobbyEntered_Set(SteamAPICall_t hSteamAPICall);
344
345 void OnLobbyMatchListCallback( LobbyMatchList_t* pCallback, bool bIOFailure );
346 CCallResult<SteamServerClientWrapper, LobbyMatchList_t> m_SteamCallResultLobbyMatchList;
347 void m_SteamCallResultLobbyMatchList_Set(SteamAPICall_t hSteamAPICall);
348
349 // Called when SteamUser()->RequestEncryptedAppTicket() returns asynchronously
350 void OnRequestEncryptedAppTicket( EncryptedAppTicketResponse_t* pEncryptedAppTicketResponse, bool bIOFailure );
351 CCallResult<SteamServerClientWrapper, EncryptedAppTicketResponse_t> m_SteamCallResultEncryptedAppTicket;
352 void m_SteamCallResultEncryptedAppTicket_Set(SteamAPICall_t hSteamAPICall);
353 void RetrieveSteamIDFromGameServer( uint32_t m_unServerIP, uint16_t m_usServerPort );
354 void GetNumberOfCurrentPlayers();
355 private:
356 void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure );
357 CCallResult< SteamServerClientWrapper, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult;
358 // simple class to marshal callbacks from pinging a game server
359 class CGameServerPing : public ISteamMatchmakingPingResponse
360 {
361 public:
CGameServerPing()362 CGameServerPing()
363 {
364 m_hGameServerQuery = HSERVERQUERY_INVALID;
365 m_pClient = NULL;
366 }
367
RetrieveSteamIDFromGameServer(SteamServerClientWrapper * pClient,uint32_t unIP,uint16_t unPort)368 void RetrieveSteamIDFromGameServer( SteamServerClientWrapper* pClient, uint32_t unIP, uint16_t unPort )
369 {
370 m_pClient = pClient;
371 m_hGameServerQuery = SteamMatchmakingServers()->PingServer( unIP, unPort, this );
372 }
373
CancelPing()374 void CancelPing()
375 {
376 m_hGameServerQuery = HSERVERQUERY_INVALID;
377 }
378
379 // Server has responded successfully and has updated data
ServerResponded(gameserveritem_t & server)380 virtual void ServerResponded( gameserveritem_t& server )
381 {
382 if ( m_hGameServerQuery != HSERVERQUERY_INVALID && server.m_steamID.IsValid() )
383 {
384 (*cpp_SteamServerClientWrapper_GameServerPingOnServerResponded)( static_cast<void*>(&server.m_steamID) );
385 }
386
387 m_hGameServerQuery = HSERVERQUERY_INVALID;
388 }
389
390 // Server failed to respond to the ping request
ServerFailedToRespond()391 virtual void ServerFailedToRespond()
392 {
393 m_hGameServerQuery = HSERVERQUERY_INVALID;
394 }
395
396 private:
397 HServerQuery m_hGameServerQuery; // we're pinging a game server so we can convert IP:Port to a steamID
398 SteamServerClientWrapper* m_pClient;
399 };
400 CGameServerPing m_GameServerPing;
401 }* steam_server_client_wrapper; //TODO: Initialize this...where?
402
403
404
OnLobbyDataUpdate(LobbyDataUpdate_t * pCallback)405 void SteamServerClientWrapper::OnLobbyDataUpdate(LobbyDataUpdate_t* pCallback)
406 {
407 if (cpp_SteamServerClientWrapper_OnLobbyDataUpdate)
408 {
409 (*cpp_SteamServerClientWrapper_OnLobbyDataUpdate)(pCallback);
410 }
411 }
412
OnLobbyMemberUpdate(LobbyChatUpdate_t * pCallback)413 void SteamServerClientWrapper::OnLobbyMemberUpdate(LobbyChatUpdate_t* pCallback)
414 {
415 if ( pCallback )
416 {
417 if ( !currentLobby )
418 {
419 printlog("[STEAM Lobbies]: Error: OnLobbyMemberUpdate: current lobby is null");
420 printlog("[STEAM Lobbies]: Warning: OnLobbyMemberUpdate received for not current lobby, leaving received lobby");
421 SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby);
422 }
423 else
424 {
425 uint64 currentLobbyID = (static_cast<CSteamID*>(currentLobby))->ConvertToUint64();
426 if ( pCallback->m_ulSteamIDLobby == currentLobbyID )
427 {
428 int numLobbyMembers = SteamMatchmaking()->GetNumLobbyMembers(currentLobbyID);
429 printlog("[STEAM Lobbies]: Info: OnLobbyMemberUpdate received, %d players", numLobbyMembers);
430 EResult userStatus = EResult::k_EResultFail;
431 for ( int lobbyMember = 0; lobbyMember < numLobbyMembers; ++lobbyMember )
432 {
433 if ( SteamMatchmaking()->GetLobbyMemberByIndex(currentLobbyID, lobbyMember).ConvertToUint64() == pCallback->m_ulSteamIDUserChanged )
434 {
435 userStatus = EResult::k_EResultOK;
436 break;
437 }
438 }
439 if ( userStatus == EResult::k_EResultFail )
440 {
441 for ( int i = 0; i < MAXPLAYERS; ++i )
442 {
443 if ( steamIDRemote[i] )
444 {
445 if ( static_cast<CSteamID*>(steamIDRemote[i])->ConvertToUint64() == pCallback->m_ulSteamIDUserChanged )
446 {
447 printlog("[STEAM Lobbies]: Info: OnLobbyMemberUpdate Player has left, NOT freeing player index %d", i);
448 //SteamNetworking()->CloseP2PSessionWithUser(*static_cast<CSteamID*>(steamIDRemote[i]));
449 //cpp_Free_CSteamID(steamIDRemote[i]);
450 //steamIDRemote[i] = nullptr;
451 }
452 }
453 }
454 }
455 else if ( userStatus == EResult::k_EResultOK )
456 {
457 for ( int i = 0; i < MAXPLAYERS; ++i )
458 {
459 if ( steamIDRemote[i] )
460 {
461 if ( static_cast<CSteamID*>(steamIDRemote[i])->ConvertToUint64() == pCallback->m_ulSteamIDUserChanged )
462 {
463 printlog("[STEAM Lobbies]: Info: OnLobbyMemberUpdate Player index %d has been updated", i);
464 }
465 }
466 }
467 }
468 }
469 else
470 {
471 printlog("[STEAM Lobbies]: Warning: OnLobbyMemberUpdate received for not current lobby, leaving received lobby");
472 SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby);
473 }
474 }
475 }
476 else
477 {
478 printlog("[STEAM Lobbies]: Error: OnLobbyMemberUpdate: null data");
479 }
480 }
481
OnP2PSessionRequest(P2PSessionRequest_t * pCallback)482 void SteamServerClientWrapper::OnP2PSessionRequest(P2PSessionRequest_t* pCallback)
483 {
484 if (cpp_SteamServerClientWrapper_OnP2PSessionRequest)
485 {
486 (*cpp_SteamServerClientWrapper_OnP2PSessionRequest)(pCallback);
487 }
488 }
489
c_RetrieveSteamIDFromGameServer(uint32_t m_unServerIP,uint16_t m_usServerPort)490 void c_RetrieveSteamIDFromGameServer( uint32_t m_unServerIP, uint16_t m_usServerPort )
491 {
492 steam_server_client_wrapper->RetrieveSteamIDFromGameServer( m_unServerIP, m_usServerPort );
493 }
494
RetrieveSteamIDFromGameServer(uint32_t m_unServerIP,uint16_t m_usServerPort)495 void SteamServerClientWrapper::RetrieveSteamIDFromGameServer( uint32_t m_unServerIP, uint16_t m_usServerPort )
496 {
497 m_GameServerPing.RetrieveSteamIDFromGameServer( this, m_unServerIP, m_usServerPort );
498 }
499
OnLobbyGameCreated(LobbyGameCreated_t * pCallback)500 void SteamServerClientWrapper::OnLobbyGameCreated(LobbyGameCreated_t* pCallback)
501 {
502 if (cpp_SteamServerClientWrapper_OnLobbyGameCreated)
503 {
504 (*cpp_SteamServerClientWrapper_OnLobbyGameCreated)(pCallback);
505 }
506 }
507
OnGameJoinRequested(GameLobbyJoinRequested_t * pCallback)508 void SteamServerClientWrapper::OnGameJoinRequested(GameLobbyJoinRequested_t* pCallback)
509 {
510 if (cpp_SteamServerClientWrapper_OnGameJoinRequested)
511 {
512 (*cpp_SteamServerClientWrapper_OnGameJoinRequested)(pCallback);
513 }
514 }
515
OnAvatarImageLoaded(AvatarImageLoaded_t * pCallback)516 void SteamServerClientWrapper::OnAvatarImageLoaded(AvatarImageLoaded_t* pCallback)
517 {
518 if (cpp_SteamServerClientWrapper_OnAvatarImageLoaded)
519 {
520 (*cpp_SteamServerClientWrapper_OnAvatarImageLoaded)(pCallback);
521 }
522 }
523
OnSteamServersConnected(SteamServersConnected_t * callback)524 void SteamServerClientWrapper::OnSteamServersConnected(SteamServersConnected_t* callback)
525 {
526 if (cpp_SteamServerClientWrapper_OnSteamServersConnected)
527 {
528 (*cpp_SteamServerClientWrapper_OnSteamServersConnected)(callback);
529 }
530 }
531
OnSteamServersDisconnected(SteamServersDisconnected_t * callback)532 void SteamServerClientWrapper::OnSteamServersDisconnected(SteamServersDisconnected_t* callback)
533 {
534 if (cpp_SteamServerClientWrapper_OnSteamServersDisconnected)
535 {
536 (*cpp_SteamServerClientWrapper_OnSteamServersDisconnected)(callback);
537 }
538 }
539
OnSteamServerConnectFailure(SteamServerConnectFailure_t * callback)540 void SteamServerClientWrapper::OnSteamServerConnectFailure(SteamServerConnectFailure_t* callback)
541 {
542 if (cpp_SteamServerClientWrapper_OnSteamServerConnectFailure)
543 {
544 (*cpp_SteamServerClientWrapper_OnSteamServerConnectFailure)(callback);
545 }
546 }
547
OnGameOverlayActivated(GameOverlayActivated_t * callback)548 void SteamServerClientWrapper::OnGameOverlayActivated(GameOverlayActivated_t* callback)
549 {
550 if (!callback)
551 {
552 return;
553 }
554
555 #ifdef STEAMDEBUG
556 printlog("OnGameOverlayActivated\n");
557 #endif
558
559 if (callback->m_bActive)
560 {
561 pauseGame(2, MAXPLAYERS);
562 SDL_SetRelativeMouseMode(SDL_FALSE); //Uncapture mouse. (Workaround for OSX Steam's inability to display a mouse in the game overlay UI)
563 SDL_ShowCursor(SDL_TRUE); //(Workaround for OSX Steam's inability to display a mouse in the game overlay UI)
564 }
565 else
566 {
567 if (shootmode && !gamePaused)
568 {
569 SDL_SetRelativeMouseMode(SDL_TRUE); //Recapture mouse.
570 }
571 SDL_ShowCursor(SDL_FALSE);
572 }
573 }
574
OnGameWebCallback(GameWebCallback_t * callback)575 void SteamServerClientWrapper::OnGameWebCallback(GameWebCallback_t* callback)
576 {
577 if (cpp_SteamServerClientWrapper_OnGameWebCallback)
578 {
579 (*cpp_SteamServerClientWrapper_OnGameWebCallback)(callback);
580 }
581 }
582
OnWorkshopItemInstalled(ItemInstalled_t * pParam)583 void SteamServerClientWrapper::OnWorkshopItemInstalled(ItemInstalled_t* pParam)
584 {
585 if (cpp_SteamServerClientWrapper_OnWorkshopItemInstalled)
586 {
587 (cpp_SteamServerClientWrapper_OnWorkshopItemInstalled)(pParam);
588 }
589 }
590
OnP2PSessionConnectFail(P2PSessionConnectFail_t * pCallback)591 void SteamServerClientWrapper::OnP2PSessionConnectFail(P2PSessionConnectFail_t* pCallback)
592 {
593 if (cpp_SteamServerClientWrapper_OnP2PSessionConnectFail)
594 {
595 (*cpp_SteamServerClientWrapper_OnP2PSessionConnectFail)(pCallback);
596 }
597 }
598
OnIPCFailure(IPCFailure_t * failure)599 void SteamServerClientWrapper::OnIPCFailure(IPCFailure_t* failure)
600 {
601 if (cpp_SteamServerClientWrapper_OnIPCFailure)
602 {
603 (*cpp_SteamServerClientWrapper_OnIPCFailure)(failure);
604 }
605 }
606
OnSteamShutdown(SteamShutdown_t * callback)607 void SteamServerClientWrapper::OnSteamShutdown(SteamShutdown_t* callback)
608 {
609 if (cpp_SteamServerClientWrapper_OnSteamShutdown)
610 {
611 (*cpp_SteamServerClientWrapper_OnSteamShutdown)(callback);
612 }
613 }
614
OnLobbyCreated(LobbyCreated_t * pCallback,bool bIOFailure)615 void SteamServerClientWrapper::OnLobbyCreated(LobbyCreated_t* pCallback, bool bIOFailure)
616 {
617 if (cpp_SteamServerClientWrapper_OnLobbyCreated)
618 {
619 (*cpp_SteamServerClientWrapper_OnLobbyCreated)(pCallback, bIOFailure);
620 }
621 }
622
m_SteamCallResultLobbyCreated_Set(SteamAPICall_t hSteamAPICall)623 void SteamServerClientWrapper::m_SteamCallResultLobbyCreated_Set(SteamAPICall_t hSteamAPICall)
624 {
625 m_SteamCallResultLobbyCreated.Set(hSteamAPICall, this, &SteamServerClientWrapper::OnLobbyCreated);
626 }
627
OnLobbyMatchListCallback(LobbyMatchList_t * pCallback,bool bIOFailure)628 void SteamServerClientWrapper::OnLobbyMatchListCallback(LobbyMatchList_t* pCallback, bool bIOFailure)
629 {
630 if (cpp_SteamServerClientWrapper_OnLobbyMatchListCallback)
631 {
632 (*cpp_SteamServerClientWrapper_OnLobbyMatchListCallback)(pCallback, bIOFailure);
633 }
634 }
635
m_SteamCallResultLobbyMatchList_Set(SteamAPICall_t hSteamAPICall)636 void SteamServerClientWrapper::m_SteamCallResultLobbyMatchList_Set(SteamAPICall_t hSteamAPICall)
637 {
638 m_SteamCallResultLobbyMatchList.Set( hSteamAPICall, this, &SteamServerClientWrapper::OnLobbyMatchListCallback );
639 }
640
OnLobbyEntered(LobbyEnter_t * pCallback,bool bIOFailure)641 void SteamServerClientWrapper::OnLobbyEntered(LobbyEnter_t* pCallback, bool bIOFailure)
642 {
643 if (cpp_SteamServerClientWrapper_OnLobbyEntered)
644 {
645 (*cpp_SteamServerClientWrapper_OnLobbyEntered)(pCallback, bIOFailure);
646 }
647 }
648
m_SteamCallResultLobbyEntered_Set(SteamAPICall_t hSteamAPICall)649 void SteamServerClientWrapper::m_SteamCallResultLobbyEntered_Set(SteamAPICall_t hSteamAPICall)
650 {
651 m_SteamCallResultLobbyEntered.Set(hSteamAPICall, this, &SteamServerClientWrapper::OnLobbyEntered);
652 }
653
OnRequestEncryptedAppTicket(EncryptedAppTicketResponse_t * pEncryptedAppTicketResponse,bool bIOFailure)654 void SteamServerClientWrapper::OnRequestEncryptedAppTicket(EncryptedAppTicketResponse_t* pEncryptedAppTicketResponse, bool bIOFailure)
655 {
656 if (cpp_SteamServerClientWrapper_OnRequestEncryptedAppTicket)
657 {
658 (*cpp_SteamServerClientWrapper_OnRequestEncryptedAppTicket)(pEncryptedAppTicketResponse, bIOFailure);
659 }
660 }
661
m_SteamCallResultEncryptedAppTicket_Set(SteamAPICall_t hSteamAPICall)662 void SteamServerClientWrapper::m_SteamCallResultEncryptedAppTicket_Set(SteamAPICall_t hSteamAPICall)
663 {
664 m_SteamCallResultEncryptedAppTicket.Set(hSteamAPICall, this, &SteamServerClientWrapper::OnRequestEncryptedAppTicket);
665 }
666
cpp_SteamMatchmaking_RequestAppTicket()667 SteamAPICall_t cpp_SteamMatchmaking_RequestAppTicket()
668 {
669 char someData[] = "data";
670 SteamAPICall_t m_SteamCallResultEncryptedAppTicket = SteamUser()->RequestEncryptedAppTicket(someData, sizeof(someData));
671 steam_server_client_wrapper->m_SteamCallResultEncryptedAppTicket_Set(m_SteamCallResultEncryptedAppTicket);
672 return m_SteamCallResultEncryptedAppTicket;
673 }
674
cpp_SteamMatchmaking_RequestLobbyList()675 SteamAPICall_t cpp_SteamMatchmaking_RequestLobbyList()
676 {
677 SteamMatchmaking()->AddRequestLobbyListNearValueFilter("lobbyCreationTime", SteamUtils()->GetServerRealTime());
678 SteamMatchmaking()->AddRequestLobbyListNumericalFilter("lobbyModifiedTime",
679 SteamUtils()->GetServerRealTime() - 8, k_ELobbyComparisonEqualToOrGreaterThan);
680 SteamAPICall_t m_SteamCallResultLobbyMatchList = SteamMatchmaking()->RequestLobbyList();
681 steam_server_client_wrapper->m_SteamCallResultLobbyMatchList_Set(m_SteamCallResultLobbyMatchList);
682 return m_SteamCallResultLobbyMatchList;
683 }
684
cpp_SteamMatchmaking_JoinLobby(CSteamID steamIDLobby)685 SteamAPICall_t cpp_SteamMatchmaking_JoinLobby(CSteamID steamIDLobby)
686 {
687 SteamAPICall_t steamAPICall = SteamMatchmaking()->JoinLobby(steamIDLobby);
688 steam_server_client_wrapper->m_SteamCallResultLobbyEntered_Set(steamAPICall);
689 return steamAPICall;
690 }
691
cpp_SteamMatchmaking_CreateLobby(ELobbyType eLobbyType,int cMaxMembers)692 SteamAPICall_t cpp_SteamMatchmaking_CreateLobby(ELobbyType eLobbyType, int cMaxMembers)
693 {
694 SteamAPICall_t steamAPICall = SteamMatchmaking()->CreateLobby(eLobbyType, cMaxMembers);
695 steam_server_client_wrapper->m_SteamCallResultLobbyCreated_Set(steamAPICall);
696 return steamAPICall;
697 }
698
cpp_SteamServerClientWrapper_Instantiate()699 void cpp_SteamServerClientWrapper_Instantiate()
700 {
701 steam_server_client_wrapper = new SteamServerClientWrapper();
702 }
703
cpp_SteamServerClientWrapper_Destroy()704 void cpp_SteamServerClientWrapper_Destroy()
705 {
706 delete steam_server_client_wrapper;
707 steam_server_client_wrapper = nullptr;
708 }
709
710 // Make the asynchronous request to receive the number of current players.
GetNumberOfCurrentPlayers()711 void SteamServerClientWrapper::GetNumberOfCurrentPlayers()
712 {
713 //printlog("Getting Number of Current Players\n");
714 SteamAPICall_t hSteamAPICall = SteamUserStats()->GetNumberOfCurrentPlayers();
715 m_NumberOfCurrentPlayersCallResult.Set(hSteamAPICall, this, &SteamServerClientWrapper::OnGetNumberOfCurrentPlayers);
716 }
717
718 // Called when SteamUserStats()->GetNumberOfCurrentPlayers() returns asynchronously, after a call to SteamAPI_RunCallbacks().
OnGetNumberOfCurrentPlayers(NumberOfCurrentPlayers_t * pCallback,bool bIOFailure)719 void SteamServerClientWrapper::OnGetNumberOfCurrentPlayers(NumberOfCurrentPlayers_t *pCallback, bool bIOFailure)
720 {
721 if ( bIOFailure || !pCallback->m_bSuccess )
722 {
723 //printlog("NumberOfCurrentPlayers_t failed!\n");
724 return;
725 }
726
727 //printlog("Number of players currently playing: %d\n", pCallback->m_cPlayers);
728 }
729
730 #endif //defined Steamworks
731
732 /* ***** END UTTER BODGE ***** */
733
734
735
736
737 /*-------------------------------------------------------------------------------
738
739 achievementUnlocked
740
741 Returns true if the given achievement has been unlocked this game,
742 false otherwise
743
744 -------------------------------------------------------------------------------*/
745
achievementUnlocked(const char * achName)746 bool achievementUnlocked(const char* achName)
747 {
748 // check internal achievement record
749 return (achievementUnlockedLookup.find(achName) != achievementUnlockedLookup.end());
750 }
751
752 /*-------------------------------------------------------------------------------
753
754 steamAchievement
755
756 Unlocks a steam achievement
757
758 -------------------------------------------------------------------------------*/
759
steamAchievement(const char * achName)760 void steamAchievement(const char* achName)
761 {
762 #ifdef DEBUG_ACHIEVEMENTS
763 messagePlayer(clientnum, "%s", achName);
764 #endif
765
766 if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
767 {
768 if ( !achievementObserver.bIsAchievementAllowedDuringTutorial(achName) )
769 {
770 return;
771 }
772 if ( conductGameChallenges[CONDUCT_CHEATS_ENABLED] )
773 {
774 return;
775 }
776 }
777 else
778 {
779 if ( conductGameChallenges[CONDUCT_CHEATS_ENABLED]
780 || conductGameChallenges[CONDUCT_LIFESAVING]
781 || gamemods_disableSteamAchievements )
782 {
783 // cheats/mods have been enabled on savefile, disallow achievements.
784 #ifndef DEBUG_ACHIEVEMENTS
785 return;
786 #endif
787 }
788 }
789
790 if ( !strcmp(achName, "BARONY_ACH_BOOTS_OF_SPEED") )
791 {
792 conductGameChallenges[CONDUCT_BOOTS_SPEED] = 1; // to cover bases when lich or devil dies as we can't remotely update this for clients.
793 }
794 //messagePlayer(clientnum, "%s", achName);
795
796 if ( !achievementUnlocked(achName) )
797 {
798 //messagePlayer(clientnum, "You've unlocked an achievement!\n [%s]",c_SteamUserStats_GetAchievementDisplayAttribute(achName,"name"));
799
800 #ifdef STEAMWORKS
801 SteamUserStats()->SetAchievement(achName);
802 SteamUserStats()->StoreStats();
803 #else
804 #ifdef USE_EOS
805 EOS.unlockAchievement(achName);
806 #endif
807 #endif
808 achievementUnlockedLookup.insert(std::string(achName));
809 }
810 }
811
steamUnsetAchievement(const char * achName)812 void steamUnsetAchievement(const char* achName)
813 {
814 #ifdef USE_EOS
815 printlog("unset achievement not supported for epic online services");
816 #endif
817 #ifndef STEAMWORKS
818 return;
819 #else
820 #ifdef DEBUG_ACHIEVEMENTS
821 SteamUserStats()->ClearAchievement(achName);
822 #endif // DEBUG_ACHIEVEMENTS
823 #endif
824 }
825
826 /*-------------------------------------------------------------------------------
827
828 steamAchievementClient
829
830 Tells a client to unlock a steam achievement (server only)
831
832 -------------------------------------------------------------------------------*/
833
steamAchievementClient(int player,const char * achName)834 void steamAchievementClient(int player, const char* achName)
835 {
836 if ( multiplayer == CLIENT )
837 {
838 return;
839 }
840
841 if ( player < 0 || player >= MAXPLAYERS )
842 {
843 return;
844 }
845 else if ( player == 0 )
846 {
847 steamAchievement(achName);
848 }
849 else
850 {
851 if ( client_disconnected[player] || multiplayer == SINGLE )
852 {
853 return;
854 }
855 strcpy((char*)net_packet->data, "SACH");
856 strcpy((char*)(&net_packet->data[4]), achName);
857 net_packet->address.host = net_clients[player - 1].host;
858 net_packet->address.port = net_clients[player - 1].port;
859 net_packet->len = 4 + strlen(achName) + 1;
860 sendPacketSafe(net_sock, -1, net_packet, player - 1);
861 }
862 }
863
steamAchievementEntity(Entity * my,const char * achName)864 void steamAchievementEntity(Entity* my, const char* achName)
865 {
866 if ( !my )
867 {
868 return;
869 }
870
871 if ( my->behavior == &actPlayer )
872 {
873 steamAchievementClient(my->skill[2], achName);
874 }
875 }
876
steamStatisticUpdate(int statisticNum,ESteamStatTypes type,int value)877 void steamStatisticUpdate(int statisticNum, ESteamStatTypes type, int value)
878 {
879 if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
880 {
881 if ( !achievementObserver.bIsStatisticAllowedDuringTutorial(static_cast<SteamStatIndexes>(statisticNum)) )
882 {
883 return;
884 }
885 if ( conductGameChallenges[CONDUCT_CHEATS_ENABLED] )
886 {
887 return;
888 }
889 }
890 else
891 {
892 if ( conductGameChallenges[CONDUCT_CHEATS_ENABLED]
893 || conductGameChallenges[CONDUCT_LIFESAVING]
894 || gamemods_disableSteamAchievements )
895 {
896 // cheats/mods have been enabled on savefile, disallow statistics update.
897 #ifndef DEBUG_ACHIEVEMENTS
898 return;
899 #endif
900 }
901 }
902
903 if ( statisticNum >= NUM_STEAM_STATISTICS || statisticNum < 0 )
904 {
905 return;
906 }
907
908 bool indicateProgress = true;
909 bool result = false;
910 switch ( type )
911 {
912 case STEAM_STAT_INT:
913 {
914 int oldValue = g_SteamStats[statisticNum].m_iValue;
915 g_SteamStats[statisticNum].m_iValue += value;
916 switch ( statisticNum )
917 {
918 case STEAM_STAT_RHINESTONE_COWBOY:
919 case STEAM_STAT_TOUGH_AS_NAILS:
920 case STEAM_STAT_UNSTOPPABLE_FORCE:
921 case STEAM_STAT_BOMBARDIER:
922 case STEAM_STAT_IN_THE_MIX:
923 case STEAM_STAT_FREE_REFILLS:
924 case STEAM_STAT_TAKE_THIS_OUTSIDE:
925 case STEAM_STAT_BLOOD_SPORT:
926 case STEAM_STAT_IRON_GUT:
927 case STEAM_STAT_BOTTLE_NOSED:
928 case STEAM_STAT_BARFIGHT_CHAMP:
929 case STEAM_STAT_VOLATILE:
930 case STEAM_STAT_SURROGATES:
931 case STEAM_STAT_KILL_COMMAND:
932 case STEAM_STAT_SPICY:
933 case STEAM_STAT_TRADITION:
934 case STEAM_STAT_POP_QUIZ:
935 case STEAM_STAT_DYSLEXIA:
936 case STEAM_STAT_BOOKWORM:
937 case STEAM_STAT_MONARCH:
938 case STEAM_STAT_MANY_PEDI_PALP:
939 case STEAM_STAT_5000_SECOND_RULE:
940 case STEAM_STAT_SOCIAL_BUTTERFLY:
941 case STEAM_STAT_ROLL_THE_BONES:
942 case STEAM_STAT_COWBOY_FROM_HELL:
943 case STEAM_STAT_SELF_FLAGELLATION:
944 case STEAM_STAT_CHOPPING_BLOCK:
945 case STEAM_STAT_IF_YOU_LOVE_SOMETHING:
946 case STEAM_STAT_RAGE_AGAINST:
947 case STEAM_STAT_GUERILLA_RADIO:
948 case STEAM_STAT_ITS_A_LIVING:
949 case STEAM_STAT_FASCIST:
950 g_SteamStats[statisticNum].m_iValue =
951 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
952 break;
953 case STEAM_STAT_ALTER_EGO:
954 indicateProgress = false;
955 g_SteamStats[statisticNum].m_iValue =
956 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
957 if ( g_SteamStats[statisticNum].m_iValue == steamStatAchStringsAndMaxVals[statisticNum].second )
958 {
959 indicateProgress = true;
960 }
961 else if ( oldValue == 0 && g_SteamStats[statisticNum].m_iValue > 0 )
962 {
963 indicateProgress = true;
964 }
965 else if ( oldValue < 1000 && ((oldValue / 1000) < (g_SteamStats[statisticNum].m_iValue / 1000)) )
966 {
967 indicateProgress = true;
968 }
969 else if ( ((oldValue / 5000) < (g_SteamStats[statisticNum].m_iValue / 5000)) )
970 {
971 indicateProgress = true;
972 }
973 break;
974 case STEAM_STAT_BAD_BLOOD:
975 indicateProgress = false;
976 g_SteamStats[statisticNum].m_iValue =
977 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
978 if ( g_SteamStats[statisticNum].m_iValue == steamStatAchStringsAndMaxVals[statisticNum].second )
979 {
980 indicateProgress = true;
981 }
982 else if ( oldValue == 0 && g_SteamStats[statisticNum].m_iValue > 0 )
983 {
984 indicateProgress = true;
985 }
986 else if ( oldValue < 20 && ((oldValue / 20) < (g_SteamStats[statisticNum].m_iValue / 20)) )
987 {
988 indicateProgress = true;
989 }
990 else if ( ((oldValue / 50) < (g_SteamStats[statisticNum].m_iValue / 50)) )
991 {
992 indicateProgress = true;
993 }
994 break;
995 case STEAM_STAT_SUPER_SHREDDER:
996 indicateProgress = false;
997 g_SteamStats[statisticNum].m_iValue =
998 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
999 if ( g_SteamStats[statisticNum].m_iValue == steamStatAchStringsAndMaxVals[statisticNum].second )
1000 {
1001 indicateProgress = true;
1002 }
1003 else if ( oldValue == 0 && g_SteamStats[statisticNum].m_iValue > 0 )
1004 {
1005 indicateProgress = true;
1006 }
1007 else if ( oldValue < 25 && ((oldValue / 25) < (g_SteamStats[statisticNum].m_iValue / 25)) )
1008 {
1009 indicateProgress = true;
1010 }
1011 else if ( ((oldValue / 50) < (g_SteamStats[statisticNum].m_iValue / 50)) ) // show every 50.
1012 {
1013 indicateProgress = true;
1014 }
1015 break;
1016 case STEAM_STAT_OVERCLOCKED:
1017 indicateProgress = false;
1018 g_SteamStats[statisticNum].m_iValue =
1019 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
1020 if ( g_SteamStats[statisticNum].m_iValue == steamStatAchStringsAndMaxVals[statisticNum].second )
1021 {
1022 indicateProgress = true;
1023 }
1024 else if ( oldValue == 0 && g_SteamStats[statisticNum].m_iValue > 0 )
1025 {
1026 indicateProgress = true;
1027 }
1028 else if ( oldValue < 30 && ((oldValue / 30) < (g_SteamStats[statisticNum].m_iValue / 30)) )
1029 {
1030 indicateProgress = true;
1031 }
1032 else if ( ((oldValue / 60) < (g_SteamStats[statisticNum].m_iValue / 60)) ) // show every 60.
1033 {
1034 indicateProgress = true;
1035 }
1036 break;
1037 case STEAM_STAT_SERIAL_THRILLA:
1038 case STEAM_STAT_TRASH_COMPACTOR:
1039 case STEAM_STAT_TORCHERER:
1040 case STEAM_STAT_FIXER_UPPER:
1041 indicateProgress = false;
1042 g_SteamStats[statisticNum].m_iValue =
1043 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
1044 if ( g_SteamStats[statisticNum].m_iValue == steamStatAchStringsAndMaxVals[statisticNum].second )
1045 {
1046 indicateProgress = true;
1047 }
1048 else if ( oldValue == 0 && g_SteamStats[statisticNum].m_iValue > 0 )
1049 {
1050 indicateProgress = true;
1051 }
1052 else if ( oldValue < 10 && ((oldValue / 10) < (g_SteamStats[statisticNum].m_iValue / 10)) )
1053 {
1054 indicateProgress = true;
1055 }
1056 else if ( ((oldValue / 25) < (g_SteamStats[statisticNum].m_iValue / 25)) ) // show every 25.
1057 {
1058 indicateProgress = true;
1059 }
1060 break;
1061 case STEAM_STAT_DIPLOMA_LVLS:
1062 case STEAM_STAT_EXTRA_CREDIT_LVLS:
1063 case STEAM_STAT_BACK_TO_BASICS:
1064 g_SteamStats[statisticNum].m_iValue =
1065 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
1066 indicateProgress = false;
1067 break;
1068 case STEAM_STAT_DIPLOMA:
1069 case STEAM_STAT_EXTRA_CREDIT:
1070 g_SteamStats[statisticNum].m_iValue =
1071 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
1072 if ( g_SteamStats[statisticNum].m_iValue == steamStatAchStringsAndMaxVals[statisticNum].second )
1073 {
1074 indicateProgress = true;
1075 }
1076 else if ( oldValue == g_SteamStats[statisticNum].m_iValue )
1077 {
1078 indicateProgress = false;
1079 }
1080 else
1081 {
1082 indicateProgress = true;
1083 }
1084 break;
1085 case STEAM_STAT_TUTORIAL_ENTERED:
1086 g_SteamStats[statisticNum].m_iValue =
1087 std::min(g_SteamStats[statisticNum].m_iValue, steamStatAchStringsAndMaxVals[statisticNum].second);
1088 if ( oldValue == 0 )
1089 {
1090 achievementObserver.updateGlobalStat(STEAM_GSTAT_TUTORIAL_ENTERED);
1091 }
1092 indicateProgress = false;
1093 break;
1094 default:
1095 break;
1096 }
1097 break;
1098 }
1099 case STEAM_STAT_FLOAT:
1100 break;
1101 default:
1102 break;
1103 }
1104 #ifdef STEAMWORKS
1105 g_SteamStatistics->StoreStats(); // update server's stat counter.
1106 #else
1107 #ifdef USE_EOS
1108 EOS.ingestStat(statisticNum, g_SteamStats[statisticNum].m_iValue);
1109 #endif
1110 #endif
1111 if ( indicateProgress )
1112 {
1113 steamIndicateStatisticProgress(statisticNum, type);
1114 }
1115 }
1116
steamStatisticUpdateClient(int player,int statisticNum,ESteamStatTypes type,int value)1117 void steamStatisticUpdateClient(int player, int statisticNum, ESteamStatTypes type, int value)
1118 {
1119 if ( gameModeManager.getMode() == GameModeManager_t::GAME_MODE_TUTORIAL )
1120 {
1121 if ( !achievementObserver.bIsStatisticAllowedDuringTutorial(static_cast<SteamStatIndexes>(statisticNum)) )
1122 {
1123 return;
1124 }
1125 if ( conductGameChallenges[CONDUCT_CHEATS_ENABLED] )
1126 {
1127 return;
1128 }
1129 }
1130 else
1131 {
1132 if ( conductGameChallenges[CONDUCT_CHEATS_ENABLED]
1133 || conductGameChallenges[CONDUCT_LIFESAVING]
1134 || gamemods_disableSteamAchievements )
1135 {
1136 // cheats/mods have been enabled on savefile, disallow statistics update.
1137 #ifndef DEBUG_ACHIEVEMENTS
1138 return;
1139 #endif
1140 }
1141 }
1142
1143 if ( statisticNum >= NUM_STEAM_STATISTICS || statisticNum < 0 )
1144 {
1145 return;
1146 }
1147
1148 if ( multiplayer == CLIENT )
1149 {
1150 return;
1151 }
1152
1153 if ( player == 0 )
1154 {
1155 steamStatisticUpdate(statisticNum, type, value);
1156 return;
1157 }
1158 else if ( player < 0 || player >= MAXPLAYERS )
1159 {
1160 return;
1161 }
1162 else
1163 {
1164 if ( client_disconnected[player] || multiplayer == SINGLE )
1165 {
1166 return;
1167 }
1168 strcpy((char*)net_packet->data, "SSTA");
1169 net_packet->data[4] = static_cast<Uint8>(statisticNum);
1170 net_packet->data[5] = static_cast<Uint8>(type);
1171 SDLNet_Write16(value, &net_packet->data[6]);
1172 net_packet->address.host = net_clients[player - 1].host;
1173 net_packet->address.port = net_clients[player - 1].port;
1174 net_packet->len = 8;
1175 sendPacketSafe(net_sock, -1, net_packet, player - 1);
1176 }
1177 }
1178
indicateAchievementProgressAndUnlock(const char * achName,int currentValue,int maxValue)1179 void indicateAchievementProgressAndUnlock(const char* achName, int currentValue, int maxValue)
1180 {
1181 #ifdef STEAMWORKS
1182 SteamUserStats()->IndicateAchievementProgress(achName, currentValue, maxValue);
1183 #elif defined USE_EOS
1184 UIToastNotificationManager.createStatisticUpdateNotification(achName, currentValue, maxValue);
1185 #endif
1186 if ( currentValue == maxValue )
1187 {
1188 steamAchievement(achName);
1189 }
1190 }
1191
steamIndicateStatisticProgress(int statisticNum,ESteamStatTypes type)1192 void steamIndicateStatisticProgress(int statisticNum, ESteamStatTypes type)
1193 {
1194 #if (!defined STEAMWORKS && !defined USE_EOS)
1195 return;
1196 #else
1197
1198 if ( statisticNum >= NUM_STEAM_STATISTICS || statisticNum < 0 )
1199 {
1200 return;
1201 }
1202
1203 int iVal = g_SteamStats[statisticNum].m_iValue;
1204 float fVal = g_SteamStats[statisticNum].m_flValue;
1205 if ( type == STEAM_STAT_INT )
1206 {
1207 switch ( statisticNum )
1208 {
1209 // below are 30-50 max value
1210 case STEAM_STAT_RHINESTONE_COWBOY:
1211 case STEAM_STAT_TOUGH_AS_NAILS:
1212 case STEAM_STAT_UNSTOPPABLE_FORCE:
1213 case STEAM_STAT_BOMBARDIER:
1214 case STEAM_STAT_IN_THE_MIX:
1215 case STEAM_STAT_FREE_REFILLS:
1216 case STEAM_STAT_BLOOD_SPORT:
1217 case STEAM_STAT_BARFIGHT_CHAMP:
1218 case STEAM_STAT_SURROGATES:
1219 case STEAM_STAT_KILL_COMMAND:
1220 case STEAM_STAT_DYSLEXIA:
1221 case STEAM_STAT_BOOKWORM:
1222 case STEAM_STAT_5000_SECOND_RULE:
1223 case STEAM_STAT_SOCIAL_BUTTERFLY:
1224 case STEAM_STAT_ROLL_THE_BONES:
1225 case STEAM_STAT_COWBOY_FROM_HELL:
1226 case STEAM_STAT_SELF_FLAGELLATION:
1227 case STEAM_STAT_FASCIST:
1228 case STEAM_STAT_ITS_A_LIVING:
1229 case STEAM_STAT_CHOPPING_BLOCK:
1230 case STEAM_STAT_MANY_PEDI_PALP:
1231 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1232 {
1233 if ( iVal == 1 || (iVal > 0 && iVal % 5 == 0) )
1234 {
1235 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1236 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1237 }
1238 }
1239 break;
1240 // below are 20 max value
1241 case STEAM_STAT_IRON_GUT:
1242 case STEAM_STAT_BOTTLE_NOSED:
1243 case STEAM_STAT_VOLATILE:
1244 case STEAM_STAT_TRADITION:
1245 case STEAM_STAT_POP_QUIZ:
1246 case STEAM_STAT_MONARCH:
1247 case STEAM_STAT_RAGE_AGAINST:
1248 case STEAM_STAT_GUERILLA_RADIO:
1249 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1250 {
1251 if ( iVal == 1 || (iVal > 0 && iVal % 4 == 0) )
1252 {
1253 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1254 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1255 }
1256 }
1257 break;
1258 case STEAM_STAT_BAD_BLOOD:
1259 case STEAM_STAT_ALTER_EGO:
1260 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1261 {
1262 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1263 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1264 }
1265 break;
1266 // below is 100 max value
1267 case STEAM_STAT_SERIAL_THRILLA:
1268 case STEAM_STAT_TRASH_COMPACTOR:
1269 case STEAM_STAT_TORCHERER:
1270 case STEAM_STAT_FIXER_UPPER:
1271 // below are 1000 max value
1272 case STEAM_STAT_SUPER_SHREDDER:
1273 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1274 {
1275 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1276 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1277 }
1278 break;
1279 // below is 600 max value
1280 case STEAM_STAT_OVERCLOCKED:
1281 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1282 {
1283 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1284 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1285 }
1286 break;
1287 // below are 100 max value
1288 case STEAM_STAT_IF_YOU_LOVE_SOMETHING:
1289 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1290 {
1291 if ( iVal == 1 || iVal == 5 || (iVal > 0 && iVal % 10 == 0) || (iVal > 0 && iVal % 25 == 0) )
1292 {
1293 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1294 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1295 }
1296 }
1297 break;
1298 // below are 10 max value
1299 case STEAM_STAT_TAKE_THIS_OUTSIDE:
1300 case STEAM_STAT_SPICY:
1301 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1302 {
1303 if ( iVal == 1 || (iVal > 0 && iVal % 2 == 0) )
1304 {
1305 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1306 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1307 }
1308 }
1309 break;
1310 case STEAM_STAT_DIPLOMA:
1311 case STEAM_STAT_EXTRA_CREDIT:
1312 if ( !achievementUnlocked(steamStatAchStringsAndMaxVals[statisticNum].first.c_str()) )
1313 {
1314 indicateAchievementProgressAndUnlock(steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1315 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1316 }
1317 break;
1318 default:
1319 break;
1320 }
1321 #ifdef DEBUG_ACHIEVEMENTS
1322 messagePlayer(clientnum, "%s: %d, %d", steamStatAchStringsAndMaxVals[statisticNum].first.c_str(),
1323 iVal, steamStatAchStringsAndMaxVals[statisticNum].second);
1324 #endif
1325 }
1326 #endif // !STEAMWORKS
1327 }
1328
1329 #ifdef STEAMWORKS
1330 //#define STEAMDEBUG
1331
1332 /*-------------------------------------------------------------------------------
1333
1334 steam callback functions
1335
1336 handle various steam callbacks; bound in init_game.c
1337
1338 -------------------------------------------------------------------------------*/
1339
1340 //Helper func. //TODO: Bugger.
cpp_P2PSessionRequest_t_m_steamIDRemote(void * P2PSessionRequest_t_instance)1341 void* cpp_P2PSessionRequest_t_m_steamIDRemote(void* P2PSessionRequest_t_instance)
1342 {
1343 CSteamID* id = new CSteamID; //TODO: Memleak?
1344 *id = static_cast<P2PSessionRequest_t*>(P2PSessionRequest_t_instance)->m_steamIDRemote;
1345 return id;
1346 }
1347
steam_OnP2PSessionRequest(void * p_Callback)1348 void steam_OnP2PSessionRequest( void* p_Callback )
1349 {
1350 #ifdef STEAMDEBUG
1351 printlog( "OnP2PSessionRequest\n" );
1352 #endif
1353 printlog("[STEAM P2P]: Received P2P session request");
1354 SteamNetworking()->AcceptP2PSessionWithUser(*static_cast<CSteamID* >(cpp_P2PSessionRequest_t_m_steamIDRemote(p_Callback)));
1355 }
1356
1357 //Helper func. //TODO: Bugger.
cpp_Free_CSteamID(void * steamID)1358 void cpp_Free_CSteamID(void* steamID)
1359 {
1360 CSteamID* id = static_cast<CSteamID*>(steamID);
1361 delete id;
1362 }
1363
1364 //Helper func. //TODO: Bugger.
cpp_SteamMatchmaking_GetLobbyByIndex(int iLobby)1365 void* cpp_SteamMatchmaking_GetLobbyByIndex(int iLobby)
1366 {
1367 CSteamID* id = new CSteamID();
1368 *id = SteamMatchmaking()->GetLobbyByIndex(iLobby);
1369 return id;
1370 }
1371
steam_OnLobbyMatchListCallback(void * pCallback,bool bIOFailure)1372 void steam_OnLobbyMatchListCallback( void* pCallback, bool bIOFailure )
1373 {
1374 if ( !requestingLobbies )
1375 {
1376 return;
1377 }
1378
1379 for ( Uint32 iLobby = 0; iLobby < MAX_STEAM_LOBBIES; iLobby++ )
1380 {
1381 if ( lobbyIDs[iLobby] )
1382 {
1383 cpp_Free_CSteamID(lobbyIDs[iLobby]); //TODO: This is an utter bodge. Make it not a list of void pointers and then just directly delete the ID.
1384 lobbyIDs[iLobby] = NULL;
1385 }
1386 }
1387 requestingLobbies = false;
1388
1389 if ( bIOFailure )
1390 {
1391 // we had a Steam I/O failure - we probably timed out talking to the Steam back-end servers
1392 // doesn't matter in this case, we can just act if no lobbies were received
1393 }
1394
1395 // lobbies are returned in order of closeness to the user, so add them to the list in that order
1396 numSteamLobbies = std::min<uint32>(static_cast<LobbyMatchList_t*>(pCallback)->m_nLobbiesMatching, MAX_STEAM_LOBBIES);
1397 for ( Uint32 iLobby = 0; iLobby < numSteamLobbies; iLobby++ )
1398 {
1399 void* steamIDLobby = cpp_SteamMatchmaking_GetLobbyByIndex( iLobby ); //TODO: Bugger this void pointer!
1400
1401 // add the lobby to the list
1402 lobbyIDs[iLobby] = steamIDLobby;
1403
1404 // pull some info from the lobby metadata (name, players, etc)
1405 const char* lobbyName = SteamMatchmaking()->GetLobbyData(*static_cast<CSteamID*>(steamIDLobby), "name"); //TODO: Again with the void pointers.
1406 const char* lobbyVersion = SteamMatchmaking()->GetLobbyData(*static_cast<CSteamID*>(steamIDLobby), "ver"); //TODO: VOID.
1407 int numPlayers = SteamMatchmaking()->GetNumLobbyMembers(*static_cast<CSteamID*>(steamIDLobby)); //TODO MORE VOID POINTERS.
1408 const char* lobbyNumMods = SteamMatchmaking()->GetLobbyData(*static_cast<CSteamID*>(steamIDLobby), "svNumMods"); //TODO: VOID.
1409 int numMods = atoi(lobbyNumMods);
1410 string versionText = lobbyVersion;
1411 if ( versionText == "" )
1412 {
1413 //If the lobby version is null
1414 versionText = "Unknown version";
1415 }
1416
1417 const Uint32 maxCharacters = 54;
1418 if ( lobbyName && lobbyName[0] && numPlayers )
1419 {
1420 // set the lobby data
1421 const Uint32 lobbyNameSize = strlen(lobbyName);
1422 std::string lobbyDetailText = " ";
1423 lobbyDetailText += "(";
1424 lobbyDetailText += versionText;
1425 lobbyDetailText += ") ";
1426 if ( numMods > 0 )
1427 {
1428 lobbyDetailText += "[MODDED]";
1429 }
1430
1431 std::string displayedLobbyName = lobbyName;
1432 if ( displayedLobbyName.size() > (maxCharacters - lobbyDetailText.size()) )
1433 {
1434 // no room, need to truncate lobbyName
1435 displayedLobbyName = displayedLobbyName.substr(0, (maxCharacters - lobbyDetailText.size()) - 2);
1436 displayedLobbyName += "..";
1437 }
1438 snprintf( lobbyText[iLobby], maxCharacters - 1, "%s%s", displayedLobbyName.c_str(), lobbyDetailText.c_str()); //TODO: Perhaps a better method would be to print the name and the version as two separate strings ( because some steam names are ridiculously long).
1439 lobbyPlayers[iLobby] = numPlayers;
1440 }
1441 else
1442 {
1443 // we don't have info about the lobby yet, request it
1444 SteamMatchmaking()->RequestLobbyData(*static_cast<CSteamID*>(steamIDLobby));
1445
1446 // results will be returned via LobbyDataUpdate_t callback
1447 snprintf( lobbyText[iLobby], maxCharacters - 1, "Lobby %d", static_cast<CSteamID*>(steamIDLobby)->GetAccountID() ); //TODO: MORE VOID POINTER BUGGERY.
1448 lobbyPlayers[iLobby] = 0;
1449 }
1450 }
1451 }
1452
1453 //Helper func. //TODO: Bugger it!
cpp_LobbyDataUpdated_pCallback_m_ulSteamIDLobby(void * pCallback)1454 void* cpp_LobbyDataUpdated_pCallback_m_ulSteamIDLobby(void* pCallback)
1455 {
1456 CSteamID* id = new CSteamID();
1457 *id = static_cast<LobbyDataUpdate_t*>(pCallback)->m_ulSteamIDLobby;
1458 return id;
1459 }
1460
steam_OnLobbyDataUpdatedCallback(void * pCallback)1461 void steam_OnLobbyDataUpdatedCallback( void* pCallback )
1462 {
1463 #ifdef STEAMDEBUG
1464 printlog( "OnLobbyDataUpdatedCallback\n" );
1465 #endif
1466 if ( LobbyHandler.steamLobbyToValidate.GetAccountID() != 0 )
1467 {
1468 LobbyDataUpdate_t* cb = static_cast<LobbyDataUpdate_t*>(pCallback);
1469 if ( cb )
1470 {
1471 if ( !cb->m_bSuccess )
1472 {
1473 printlog("[STEAM Lobbies]: Lobby to join no longer exists");
1474 connectingToLobbyStatus = LobbyHandler_t::EResult_LobbyFailures::LOBBY_NOT_FOUND;
1475 connectingToLobbyWindow = false;
1476 connectingToLobby = false;
1477 }
1478 else if ( cb->m_ulSteamIDLobby == LobbyHandler.steamLobbyToValidate.ConvertToUint64() )
1479 {
1480 printlog("[STEAM Lobbies]: Received update for join lobby request");
1481 if ( LobbyHandler.validateSteamLobbyDataOnJoin() )
1482 {
1483 printlog("[STEAM Lobbies]: Join lobby request initiated");
1484 cpp_SteamMatchmaking_JoinLobby(LobbyHandler.steamLobbyToValidate);
1485 }
1486 else
1487 {
1488 printlog("[STEAM Lobbies]: Incompatible lobby to join");
1489 }
1490 }
1491 LobbyHandler.steamLobbyToValidate.SetAccountID(0);
1492 return;
1493 }
1494 }
1495
1496 // finish processing lobby invite?
1497 if ( stillConnectingToLobby )
1498 {
1499 stillConnectingToLobby = false;
1500
1501 void processLobbyInvite();
1502 processLobbyInvite();
1503 return;
1504 }
1505
1506 // update current lobby info
1507 void* tempSteamID = cpp_LobbyDataUpdated_pCallback_m_ulSteamIDLobby(pCallback); //TODO: BUGGER VOID POINTER.
1508 if ( currentLobby )
1509 {
1510 if ( (static_cast<CSteamID*>(currentLobby))->ConvertToUint64() == (static_cast<CSteamID*>(tempSteamID))->ConvertToUint64() )
1511 {
1512 // extract the display name from the lobby metadata
1513 const char* lobbyName = SteamMatchmaking()->GetLobbyData( *static_cast<CSteamID*>(currentLobby), "name" );
1514 if ( lobbyName )
1515 {
1516 snprintf( currentLobbyName, 31, lobbyName );
1517 }
1518
1519 // get the server flags
1520 const char* svFlagsChar = SteamMatchmaking()->GetLobbyData( *static_cast<CSteamID*>(currentLobby), "svFlags" );
1521 if ( svFlagsChar )
1522 {
1523 svFlags = atoi(svFlagsChar);
1524 }
1525 }
1526 }
1527 cpp_Free_CSteamID(tempSteamID);
1528 }
1529
1530 //Helper func. //TODO: BUGGER THIS.
cpp_LobbyCreated_Lobby(void * pCallback)1531 void* cpp_LobbyCreated_Lobby(void* pCallback)
1532 {
1533 CSteamID* id = new CSteamID;
1534 *id = static_cast<LobbyCreated_t*>(pCallback)->m_ulSteamIDLobby;
1535 return id;
1536 }
1537
steam_OnLobbyCreated(void * pCallback,bool bIOFailure)1538 void steam_OnLobbyCreated( void* pCallback, bool bIOFailure )
1539 {
1540 #ifdef STEAMDEBUG
1541 printlog( "OnLobbyCreated\n" );
1542 #endif
1543 if ( static_cast<EResult>(static_cast<LobbyCreated_t*>(pCallback)->m_eResult) == k_EResultOK ) //TODO: Make sure port from c_EResult to EResult works flawlessly.
1544 {
1545 if ( currentLobby )
1546 {
1547 SteamMatchmaking()->LeaveLobby(*static_cast<CSteamID*>(currentLobby));
1548 cpp_Free_CSteamID(currentLobby); //TODO: BUGGER THIS.
1549 currentLobby = nullptr;
1550 }
1551 currentLobby = cpp_LobbyCreated_Lobby(pCallback);
1552
1553 // set the name of the lobby
1554 snprintf( currentLobbyName, 31, "%s's lobby", SteamFriends()->GetPersonaName() );
1555 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "name", currentLobbyName); //TODO: Bugger void pointer!
1556
1557 // set the game version of the lobby
1558 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "ver", VERSION); //TODO: Bugger void pointer!
1559
1560 // set lobby server flags
1561 char svFlagsChar[16];
1562 snprintf(svFlagsChar, 15, "%d", svFlags);
1563 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "svFlags", svFlagsChar); //TODO: Bugger void pointer!
1564
1565 // set load game status on lobby
1566 char loadingsavegameChar[16];
1567 snprintf(loadingsavegameChar, 15, "%d", loadingsavegame);
1568 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "loadingsavegame", loadingsavegameChar); //TODO: Bugger void pointer!
1569
1570 char svNumMods[16];
1571 snprintf(svNumMods, 15, "%d", gamemods_numCurrentModsLoaded);
1572 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "svNumMods", svNumMods); //TODO: Bugger void pointer!
1573
1574 char modifiedTime[32];
1575 snprintf(modifiedTime, 31, "%d", SteamUtils()->GetServerRealTime());
1576 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "lobbyModifiedTime", modifiedTime); //TODO: Bugger void pointer!
1577 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), "lobbyCreationTime", modifiedTime); //TODO: Bugger void pointer!
1578
1579 if ( gamemods_numCurrentModsLoaded > 0 )
1580 {
1581 int count = 0;
1582 for ( std::vector<std::pair<std::string, std::string>>::iterator it = gamemods_mountedFilepaths.begin(); it != gamemods_mountedFilepaths.end(); ++it )
1583 {
1584 for ( std::vector<std::pair<std::string, uint64>>::iterator itMap = gamemods_workshopLoadedFileIDMap.begin();
1585 itMap != gamemods_workshopLoadedFileIDMap.end(); ++itMap )
1586 {
1587 if ( (itMap->first).compare(it->second) == 0 )
1588 {
1589 char svModFileID[64];
1590 snprintf(svModFileID, 64, "%d", static_cast<int>(itMap->second));
1591 char tagName[32] = "";
1592 snprintf(tagName, 32, "svMod%d", count);
1593 SteamMatchmaking()->SetLobbyData(*static_cast<CSteamID*>(currentLobby), tagName, svModFileID); //TODO: Bugger void pointer!
1594 ++count;
1595 break;
1596 }
1597 }
1598 }
1599 }
1600 }
1601 else
1602 {
1603 printlog( "warning: failed to create steam lobby.\n");
1604 }
1605 }
1606
1607 #ifdef USE_EOS
steam_OnRequestEncryptedAppTicket(void * pCallback,bool bIOFailure)1608 void steam_OnRequestEncryptedAppTicket(void* pCallback, bool bIOFailure)
1609 {
1610 if ( bIOFailure )
1611 {
1612 printlog("OnRequestEncryptedAppTicket failure");
1613 return;
1614 }
1615
1616 EncryptedAppTicketResponse_t* cb = static_cast<EncryptedAppTicketResponse_t*>(pCallback);
1617 switch ( cb->m_eResult )
1618 {
1619 case k_EResultOK:
1620 {
1621 uint8 rgubTicket[1024];
1622 uint32 cubTicket;
1623 if ( SteamUser()->GetEncryptedAppTicket(rgubTicket, sizeof(rgubTicket), &cubTicket) )
1624 {
1625 char buf[1024] = "";
1626 Uint32 len = 1024;
1627 EOS_EResult result = EOS_ByteArray_ToString(rgubTicket, cubTicket, buf, &len);
1628 if ( result != EOS_EResult::EOS_Success )
1629 {
1630 printlog("EOS_ByteArray_ToString failed, error code: %d", static_cast<int>(result));
1631 }
1632 EOS.ConnectHandle = EOS_Platform_GetConnectInterface(EOS.PlatformHandle);
1633 EOS_Connect_Credentials Credentials;
1634 Credentials.ApiVersion = EOS_CONNECT_CREDENTIALS_API_LATEST;
1635 Credentials.Token = buf;
1636 Credentials.Type = EOS_EExternalCredentialType::EOS_ECT_STEAM_APP_TICKET; // change this to steam etc for different account providers.
1637
1638 EOS_Connect_LoginOptions Options;
1639 Options.ApiVersion = EOS_CONNECT_LOGIN_API_LATEST;
1640 Options.Credentials = &Credentials;
1641 Options.UserLoginInfo = nullptr;
1642
1643 EOS_Connect_Login(EOS.ConnectHandle, &Options, nullptr, EOS.ConnectLoginCrossplayCompleteCallback);
1644 EOS.CrossplayAccountManager.awaitingConnectCallback = true;
1645 EOS.CrossplayAccountManager.awaitingAppTicketResponse = false;
1646 printlog("[STEAM]: AppTicket request success");
1647 }
1648 else
1649 {
1650 printlog("GetEncryptedAppTicket failed");
1651 }
1652 }
1653 break;
1654 case k_EResultNoConnection:
1655 printlog("OnRequestEncryptedAppTicket no steam connection");
1656 break;
1657 case k_EResultDuplicateRequest:
1658 printlog("OnRequestEncryptedAppTicket duplicate request outstanding");
1659 break;
1660 case k_EResultLimitExceeded:
1661 printlog("OnRequestEncryptedAppTicket called more than once per minute");
1662 break;
1663 default:
1664 break;
1665 }
1666 }
1667 #endif //USE_EOS
1668
processLobbyInvite()1669 void processLobbyInvite()
1670 {
1671 if ( !intro )
1672 {
1673 stillConnectingToLobby = true;
1674 return;
1675 }
1676 if ( !lobbyToConnectTo )
1677 {
1678 printlog( "warning: tried to process invitation to null lobby" );
1679 stillConnectingToLobby = false;
1680 return;
1681 }
1682 const char* loadingSaveGameChar = SteamMatchmaking()->GetLobbyData( *static_cast<CSteamID*>(lobbyToConnectTo), "loadingsavegame" );
1683
1684 if ( loadingSaveGameChar && loadingSaveGameChar[0] )
1685 {
1686 Uint32 temp32 = atoi(loadingSaveGameChar);
1687 Uint32 gameKey = getSaveGameUniqueGameKey(false);
1688 if ( temp32 && temp32 == gameKey )
1689 {
1690 loadingsavegame = temp32;
1691 buttonLoadMultiplayerGame(NULL);
1692 }
1693 else if ( !temp32 )
1694 {
1695 loadingsavegame = 0;
1696 buttonOpenCharacterCreationWindow(NULL);
1697 }
1698 else
1699 {
1700 // try reload from your other savefiles since this didn't match the default savegameIndex.
1701 if ( savegamesList.empty() )
1702 {
1703 reloadSavegamesList(false);
1704 }
1705 bool foundSave = false;
1706 for ( auto it = savegamesList.begin(); it != savegamesList.end(); ++it )
1707 {
1708 auto entry = *it;
1709 savegameCurrentFileIndex = std::get<2>(entry);
1710 gameKey = getSaveGameUniqueGameKey(false, savegameCurrentFileIndex);
1711 if ( std::get<1>(entry) != SINGLE && temp32 == gameKey )
1712 {
1713 foundSave = true;
1714 break;
1715 }
1716 }
1717
1718 if ( !foundSave )
1719 {
1720 savegameCurrentFileIndex = 0;
1721 printlog("warning: received invitation to lobby with which you have an incompatible save game.\n");
1722 if ( lobbyToConnectTo )
1723 {
1724 cpp_Free_CSteamID(lobbyToConnectTo); //TODO: Bodge this bodge!
1725 }
1726 lobbyToConnectTo = NULL;
1727 }
1728 else
1729 {
1730 loadingsavegame = temp32;
1731 buttonLoadMultiplayerGame(NULL);
1732 }
1733 }
1734 stillConnectingToLobby = false;
1735 }
1736 else
1737 {
1738 stillConnectingToLobby = true;
1739 SteamMatchmaking()->RequestLobbyData(*static_cast<CSteamID*>(lobbyToConnectTo));
1740 printlog("warning: failed to determine whether lobby is using a saved game or not...\n");
1741 }
1742 }
1743
1744 //Helper func. //TODO: Bugger.
cpp_GameJoinRequested_m_steamIDLobby(void * pCallback)1745 void* cpp_GameJoinRequested_m_steamIDLobby(void* pCallback)
1746 {
1747 CSteamID* id = new CSteamID;
1748 *id = static_cast<GameLobbyJoinRequested_t*>(pCallback)->m_steamIDLobby;
1749 return id;
1750 }
1751
steam_OnGameJoinRequested(void * pCallback)1752 void steam_OnGameJoinRequested( void* pCallback )
1753 {
1754 #ifdef STEAMDEBUG
1755 printlog( "OnGameJoinRequested\n" );
1756 #endif
1757
1758 // return to a state where we can join the lobby
1759 if ( !intro )
1760 {
1761 buttonEndGameConfirm(NULL);
1762 }
1763 else if ( multiplayer != SINGLE )
1764 {
1765 buttonDisconnect(NULL);
1766 }
1767
1768 // close current window
1769 if ( subwindow )
1770 {
1771 if ( score_window )
1772 {
1773 // reset class loadout
1774 stats[0]->sex = static_cast<sex_t>(0);
1775 stats[0]->appearance = 0;
1776 stats[0]->playerRace = RACE_HUMAN;
1777 strcpy(stats[0]->name, "");
1778 stats[0]->type = HUMAN;
1779 client_classes[0] = 0;
1780 stats[0]->clearStats();
1781 initClass(0);
1782 }
1783 score_window = 0;
1784 gamemods_window = 0;
1785 lobby_window = false;
1786 settings_window = false;
1787 charcreation_step = 0;
1788 subwindow = 0;
1789 if ( SDL_IsTextInputActive() )
1790 {
1791 SDL_StopTextInput();
1792 }
1793 }
1794 list_FreeAll(&button_l);
1795 deleteallbuttons = true;
1796
1797 if ( lobbyToConnectTo )
1798 {
1799 cpp_Free_CSteamID(lobbyToConnectTo); //TODO: Utter bodge.
1800 }
1801 lobbyToConnectTo = cpp_GameJoinRequested_m_steamIDLobby(pCallback);
1802 processLobbyInvite();
1803 }
1804
1805 //Helper func. //TODO: Bugger.
cpp_SteamMatchmaking_JoinLobbyPCH(const char * pchLobbyID)1806 void cpp_SteamMatchmaking_JoinLobbyPCH(const char* pchLobbyID)
1807 {
1808 CSteamID steamIDLobby( (uint64)atoll( pchLobbyID ) );
1809 if ( steamIDLobby.IsValid() )
1810 {
1811 SteamAPICall_t steamAPICall = SteamMatchmaking()->JoinLobby(steamIDLobby);
1812 steam_server_client_wrapper->m_SteamCallResultLobbyEntered_Set(steamAPICall);
1813 }
1814 }
1815
1816 // searches (char pchCmdLine[]) for a connect lobby command
steam_ConnectToLobby()1817 void steam_ConnectToLobby()
1818 {
1819 #ifdef STEAMDEBUG
1820 printlog( "ConnectToLobby\n" );
1821 #endif
1822
1823 // parse out the connect
1824 char pchLobbyID[1024];
1825
1826 // look for +connect_lobby command
1827 const char* pchConnectLobbyParam = "+connect_lobby";
1828 const char* pchConnectLobby = strstr( pchCmdLine, pchConnectLobbyParam );
1829 if ( pchConnectLobby )
1830 {
1831 // address should be right after the +connect_lobby, +1 on the end to skip the space
1832 strcpy( pchLobbyID, (char*)(pchConnectLobby + strlen(pchConnectLobbyParam) + 1 ));
1833 }
1834
1835 // join lobby
1836 if ( pchLobbyID )
1837 {
1838 //c_SteamMatchmaking_JoinLobbyPCH( pchLobbyID, &steam_OnLobbyEntered );
1839 cpp_SteamMatchmaking_JoinLobbyPCH( pchLobbyID);
1840 }
1841 }
1842
cpp_pCallback_m_ulSteamIDLobby(void * pCallback)1843 void* cpp_pCallback_m_ulSteamIDLobby( void* pCallback )
1844 {
1845 CSteamID* id = new CSteamID();
1846 *id = static_cast<LobbyEnter_t*>(pCallback)->m_ulSteamIDLobby;
1847 return id;
1848 }
1849
steam_OnLobbyEntered(void * pCallback,bool bIOFailure)1850 void steam_OnLobbyEntered( void* pCallback, bool bIOFailure )
1851 {
1852 #ifdef STEAMDEBUG
1853 printlog( "OnLobbyEntered\n" );
1854 #endif
1855 if ( denyLobbyJoinEvent || !connectingToLobby )
1856 {
1857 if ( denyLobbyJoinEvent )
1858 {
1859 printlog("[STEAM Lobbies]: Forcibly denying joining current lobby");
1860 }
1861 else if ( !connectingToLobby )
1862 {
1863 printlog("[STEAM Lobbies]: On lobby entered, unexpected closed window. Leaving lobby");
1864 }
1865 denyLobbyJoinEvent = false;
1866 if ( pCallback )
1867 {
1868 if ( static_cast<LobbyEnter_t*>(pCallback)->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess )
1869 {
1870 SteamMatchmaking()->LeaveLobby(static_cast<LobbyEnter_t*>(pCallback)->m_ulSteamIDLobby);
1871 }
1872 }
1873 if ( currentLobby )
1874 {
1875 SteamMatchmaking()->LeaveLobby(*static_cast<CSteamID*>(currentLobby));
1876 cpp_Free_CSteamID(currentLobby); //TODO: Bugger.
1877 currentLobby = nullptr;
1878 }
1879 connectingToLobby = false;
1880 connectingToLobbyWindow = false;
1881 return;
1882 }
1883
1884 denyLobbyJoinEvent = false;
1885
1886 if ( static_cast<LobbyEnter_t*>(pCallback)->m_EChatRoomEnterResponse != k_EChatRoomEnterResponseSuccess )
1887 {
1888 // lobby join failed
1889 connectingToLobby = false;
1890 connectingToLobbyWindow = false;
1891 openFailedConnectionWindow(CLIENT);
1892 return;
1893 }
1894
1895 // success
1896
1897 // move forward the state
1898 if ( currentLobby )
1899 {
1900 SteamMatchmaking()->LeaveLobby(*static_cast<CSteamID*>(currentLobby));
1901 cpp_Free_CSteamID(currentLobby); //TODO: Bugger.
1902 currentLobby = nullptr;
1903 }
1904 currentLobby = cpp_pCallback_m_ulSteamIDLobby(pCallback); //TODO: More buggery.
1905 connectingToLobby = false;
1906 }
1907
steam_GameServerPingOnServerResponded(void * steamID)1908 void steam_GameServerPingOnServerResponded(void* steamID)
1909 {
1910 #ifdef STEAMDEBUG
1911 printlog( "GameServerPingOnServerResponded\n" );
1912 #endif
1913
1914 steamIDGameServer = steamID;
1915 }
1916
steam_OnP2PSessionConnectFail(void * pCallback)1917 void steam_OnP2PSessionConnectFail( void* pCallback )
1918 {
1919 #ifdef STEAMDEBUG
1920 printlog( "OnP2PSessionConnectFail\n" );
1921 #endif
1922
1923 printlog("[STEAM P2P]: Warning: failed to establish steam P2P connection.\n");
1924
1925 /*if ( intro )
1926 {
1927 connectingToLobby = false;
1928 connectingToLobbyWindow = false;
1929 buttonDisconnect(nullptr);
1930 openFailedConnectionWindow(SINGLE);
1931 }*/
1932 }
1933
FindLeaderboard(const char * pchLeaderboardName)1934 void CSteamLeaderboards::FindLeaderboard(const char *pchLeaderboardName)
1935 {
1936 if ( !SteamUser()->BLoggedOn() )
1937 {
1938 return;
1939 }
1940 m_CurrentLeaderboard = NULL;
1941 b_LeaderboardInit = false;
1942 SteamAPICall_t hSteamAPICall = SteamUserStats()->FindLeaderboard(pchLeaderboardName);
1943 m_callResultFindLeaderboard.Set(hSteamAPICall, this,
1944 &CSteamLeaderboards::OnFindLeaderboard);
1945 // call OnFindLeaderboard when result of async API call
1946 }
1947
OnFindLeaderboard(LeaderboardFindResult_t * pCallback,bool bIOFailure)1948 void CSteamLeaderboards::OnFindLeaderboard(LeaderboardFindResult_t *pCallback, bool bIOFailure)
1949 {
1950 // see if we encountered an error during the call
1951 if ( !pCallback->m_bLeaderboardFound || bIOFailure )
1952 {
1953 printlog("[STEAM]: Error, could not find leaderboard %s!", leaderboardNames[LeaderboardUpload.boardIndex].c_str());
1954 ClearUploadData();
1955 return;
1956 }
1957 b_LeaderboardInit = true;
1958 m_CurrentLeaderboard = pCallback->m_hSteamLeaderboard;
1959 //DownloadScores(k_ELeaderboardDataRequestGlobal, 0, k_numEntriesToRetrieve);
1960 }
1961
DownloadScores(ELeaderboardDataRequest dataRequestType,int rangeStart,int rangeEnd)1962 bool CSteamLeaderboards::DownloadScores(ELeaderboardDataRequest dataRequestType, int rangeStart, int rangeEnd)
1963 {
1964 if ( !m_CurrentLeaderboard )
1965 {
1966 return false;
1967 }
1968 b_ScoresDownloaded = false;
1969
1970 // load the specified leaderboard data around the current user
1971 SteamAPICall_t hSteamAPICall = SteamUserStats()->DownloadLeaderboardEntries(
1972 m_CurrentLeaderboard, dataRequestType, rangeStart, rangeEnd);
1973 m_callResultDownloadScore.Set(hSteamAPICall, this,
1974 &CSteamLeaderboards::OnDownloadScore);
1975
1976 return true;
1977 }
1978
OnDownloadScore(LeaderboardScoresDownloaded_t * pCallback,bool bIOFailure)1979 void CSteamLeaderboards::OnDownloadScore(LeaderboardScoresDownloaded_t *pCallback, bool bIOFailure)
1980 {
1981 if ( !bIOFailure )
1982 {
1983 m_nLeaderboardEntries = std::min(pCallback->m_cEntryCount, (int)CSteamLeaderboards::k_numEntriesToRetrieve);
1984 for ( int i = 0; i < m_nLeaderboardEntries; ++i )
1985 {
1986 SteamUserStats()->GetDownloadedLeaderboardEntry(pCallback->m_hSteamLeaderboardEntries,
1987 i, &m_leaderboardEntries[i], downloadedTags[i], k_numLeaderboardTags);
1988 leaderBoardSteamUsernames[i] = SteamFriends()->GetFriendPersonaName(m_leaderboardEntries[i].m_steamIDUser);
1989 }
1990 b_ScoresDownloaded = true;
1991 }
1992 }
1993
UploadScore(int scoreToSet,int tags[k_numLeaderboardTags])1994 void CSteamLeaderboards::UploadScore(int scoreToSet, int tags[k_numLeaderboardTags])
1995 {
1996 if ( !m_CurrentLeaderboard )
1997 {
1998 return;
1999 }
2000
2001 // load the specified leaderboard data around the current user
2002 SteamAPICall_t hSteamAPICall = SteamUserStats()->UploadLeaderboardScore(m_CurrentLeaderboard,
2003 k_ELeaderboardUploadScoreMethodKeepBest, scoreToSet, tags,
2004 k_numLeaderboardTags);
2005 m_callResultUploadScore.Set(hSteamAPICall, this,
2006 &CSteamLeaderboards::OnUploadScore);
2007 }
2008
OnUploadScore(LeaderboardScoreUploaded_t * pCallback,bool bIOFailure)2009 void CSteamLeaderboards::OnUploadScore(LeaderboardScoreUploaded_t *pCallback, bool bIOFailure)
2010 {
2011 if ( !bIOFailure && pCallback->m_bSuccess )
2012 {
2013 m_CurrentLeaderboard = pCallback->m_hSteamLeaderboard;
2014 LastUploadResult.b_ScoreUploadComplete = (pCallback->m_bSuccess == 1);
2015 LastUploadResult.b_ScoreChanged = (pCallback->m_bScoreChanged != 0);
2016 LastUploadResult.globalRankNew = pCallback->m_nGlobalRankNew;
2017 LastUploadResult.globalRankPrev = pCallback->m_nGlobalRankPrevious;
2018 LastUploadResult.scoreUploaded = pCallback->m_nScore;
2019 }
2020 else
2021 {
2022 LastUploadResult.b_ScoreUploadComplete = false;
2023 LastUploadResult.b_ScoreChanged = false;
2024 LastUploadResult.globalRankNew = 0;
2025 LastUploadResult.globalRankPrev = 0;
2026 LastUploadResult.scoreUploaded = 0;
2027 }
2028 }
2029
ClearUploadData()2030 void CSteamLeaderboards::ClearUploadData()
2031 {
2032 for ( int c = 0; c < k_numLeaderboardTags; ++c )
2033 {
2034 LeaderboardUpload.tags[c] = 0;
2035 }
2036 LeaderboardUpload.score = 0;
2037 LeaderboardUpload.time = 0;
2038 LeaderboardUpload.status = LEADERBOARD_STATE_NONE;
2039 LeaderboardUpload.boardIndex = LEADERBOARD_NONE;
2040 LeaderboardUpload.uploadInit = false;
2041
2042 LastUploadResult.b_ScoreChanged = false;
2043 LastUploadResult.b_ScoreUploadComplete = false;
2044 LastUploadResult.globalRankNew = 0;
2045 LastUploadResult.globalRankPrev;
2046 LastUploadResult.scoreUploaded = 0;
2047 }
2048
ProcessLeaderboardUpload()2049 void CSteamLeaderboards::ProcessLeaderboardUpload()
2050 {
2051 if ( LeaderboardUpload.status == LEADERBOARD_STATE_NONE )
2052 {
2053 return;
2054 }
2055
2056 if ( ticks % 25 == 0 )
2057 {
2058 if ( LeaderboardUpload.status == LEADERBOARD_STATE_FIND_LEADERBOARD_TIME )
2059 {
2060 FindLeaderboard(leaderboardNames[LeaderboardUpload.boardIndex].c_str());
2061 LeaderboardUpload.status = LEADERBOARD_STATE_UPLOADING_TIME;
2062 LastUploadResult.b_ScoreUploadComplete = false;
2063 LastUploadResult.b_ScoreChanged = false;
2064 }
2065 else if ( LeaderboardUpload.status == LEADERBOARD_STATE_UPLOADING_TIME )
2066 {
2067 if ( b_LeaderboardInit )
2068 {
2069 if ( !LeaderboardUpload.uploadInit )
2070 {
2071 UploadScore(LeaderboardUpload.time, LeaderboardUpload.tags);
2072 LeaderboardUpload.uploadInit = true;
2073 }
2074 if ( LastUploadResult.b_ScoreUploadComplete == true )
2075 {
2076 LeaderboardUpload.uploadInit = false;
2077 LeaderboardUpload.status = LEADERBOARD_STATE_READY_TIME;
2078 printlog("[STEAM]: Successfully uploaded leaderboard time to board name %s.", leaderboardNames[LeaderboardUpload.boardIndex].c_str());
2079 if ( LastUploadResult.b_ScoreChanged )
2080 {
2081 printlog("[STEAM]: Registered a new fastest time on the leaderboard!");
2082 }
2083 else
2084 {
2085 printlog("[STEAM]: You did not beat your previous leaderboard time.");
2086 }
2087 LastUploadResult.b_ScoreUploadComplete = false;
2088 }
2089 }
2090 }
2091 else if ( LeaderboardUpload.status == LEADERBOARD_STATE_READY_TIME )
2092 {
2093 FindLeaderboard(leaderboardNames[LeaderboardUpload.boardIndex + 1].c_str());
2094 LeaderboardUpload.status = LEADERBOARD_STATE_UPLOADING_SCORE;
2095 LastUploadResult.b_ScoreUploadComplete = false;
2096 LastUploadResult.b_ScoreChanged = false;
2097 }
2098 else if ( LeaderboardUpload.status == LEADERBOARD_STATE_UPLOADING_SCORE )
2099 {
2100 if ( b_LeaderboardInit )
2101 {
2102 if ( !LeaderboardUpload.uploadInit )
2103 {
2104 UploadScore(LeaderboardUpload.score, LeaderboardUpload.tags);
2105 LeaderboardUpload.uploadInit = true;
2106 }
2107 if ( LastUploadResult.b_ScoreUploadComplete == true )
2108 {
2109 LeaderboardUpload.uploadInit = false;
2110 LeaderboardUpload.status = LEADERBOARD_STATE_NONE;
2111 printlog("[STEAM]: Successfully uploaded leaderboard score to board name %s.", leaderboardNames[LeaderboardUpload.boardIndex + 1].c_str());
2112 LastUploadResult.b_ScoreUploadComplete = false;
2113 if ( LastUploadResult.b_ScoreChanged )
2114 {
2115 printlog("[STEAM]: Registered a new highest score on the leaderboard!");
2116 }
2117 else
2118 {
2119 printlog("[STEAM]: You did not beat your previous leaderboard score.");
2120 }
2121 ClearUploadData();
2122 DownloadScores(k_ELeaderboardDataRequestGlobal, 0, k_numEntriesToRetrieve);
2123 }
2124 }
2125 }
2126 }
2127 }
2128 #endif