simplify gitignore
[vg.git] / src / vg / vg_steamworks.h
1 #if defined(__linux__) || defined(__APPLE__)
2 // The 32-bit version of gcc has the alignment requirement for u64 and double set to
3 // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
4 // The 64-bit version of gcc has the alignment requirement for these types set to
5 // 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
6 // The 64-bit structure packing has to match the 32-bit structure packing for each platform.
7 #define VALVE_CALLBACK_PACK_SMALL
8 #else
9 #define VALVE_CALLBACK_PACK_LARGE
10 #endif
11
12 #if defined( VALVE_CALLBACK_PACK_SMALL )
13 #pragma pack( push, 4 )
14 #elif defined( VALVE_CALLBACK_PACK_LARGE )
15 #pragma pack( push, 8 )
16 #else
17 #error steam_api_common.h should define VALVE_CALLBACK_PACK_xxx
18 #endif
19
20 // Types
21 typedef void ISteamFriends;
22 typedef void ISteamUserStats;
23 typedef void ISteamUtils;
24 typedef void ISteamUser;
25 typedef void ISteamNetworking;
26
27 typedef i32 HSteamPipe;
28 typedef i32 HSteamUser;
29
30 typedef int E_iCallBack_t;
31
32 typedef u32 SNetSocket_t; // CreateP2PConnectionSocket()
33 typedef u32 SNetListenSocket_t; // CreateListenSocket()
34
35 typedef u64 u64_steamid;
36 typedef u64 SteamAPICall_t;
37
38 enum { k_iSteamUserCallbacks = 100 };
39 enum { k_iSteamGameServerCallbacks = 200 };
40 enum { k_iSteamFriendsCallbacks = 300 };
41 enum { k_iSteamBillingCallbacks = 400 };
42 enum { k_iSteamMatchmakingCallbacks = 500 };
43 enum { k_iSteamContentServerCallbacks = 600 };
44 enum { k_iSteamUtilsCallbacks = 700 };
45 enum { k_iClientFriendsCallbacks = 800 };
46 enum { k_iClientUserCallbacks = 900 };
47 enum { k_iSteamAppsCallbacks = 1000 };
48 enum { k_iSteamUserStatsCallbacks = 1100 };
49 enum { k_iSteamNetworkingCallbacks = 1200 };
50 enum { k_iSteamNetworkingSocketsCallbacks = 1220 };
51 enum { k_iSteamNetworkingMessagesCallbacks = 1250 };
52 enum { k_iSteamNetworkingUtilsCallbacks = 1280 };
53 enum { k_iClientRemoteStorageCallbacks = 1300 };
54 enum { k_iClientDepotBuilderCallbacks = 1400 };
55 enum { k_iSteamGameServerItemsCallbacks = 1500 };
56 enum { k_iClientUtilsCallbacks = 1600 };
57 enum { k_iSteamGameCoordinatorCallbacks = 1700 };
58 enum { k_iSteamGameServerStatsCallbacks = 1800 };
59 enum { k_iSteam2AsyncCallbacks = 1900 };
60 enum { k_iSteamGameStatsCallbacks = 2000 };
61 enum { k_iClientHTTPCallbacks = 2100 };
62 enum { k_iClientScreenshotsCallbacks = 2200 };
63 enum { k_iSteamScreenshotsCallbacks = 2300 };
64 enum { k_iClientAudioCallbacks = 2400 };
65 enum { k_iClientUnifiedMessagesCallbacks = 2500 };
66 enum { k_iSteamStreamLauncherCallbacks = 2600 };
67 enum { k_iClientControllerCallbacks = 2700 };
68 enum { k_iSteamControllerCallbacks = 2800 };
69 enum { k_iClientParentalSettingsCallbacks = 2900 };
70 enum { k_iClientDeviceAuthCallbacks = 3000 };
71 enum { k_iClientNetworkDeviceManagerCallbacks = 3100 };
72 enum { k_iClientMusicCallbacks = 3200 };
73 enum { k_iClientRemoteClientManagerCallbacks = 3300 };
74 enum { k_iClientUGCCallbacks = 3400 };
75 enum { k_iSteamStreamClientCallbacks = 3500 };
76 enum { k_IClientProductBuilderCallbacks = 3600 };
77 enum { k_iClientShortcutsCallbacks = 3700 };
78 enum { k_iClientRemoteControlManagerCallbacks = 3800 };
79 enum { k_iSteamAppListCallbacks = 3900 };
80 enum { k_iSteamMusicCallbacks = 4000 };
81 enum { k_iSteamMusicRemoteCallbacks = 4100 };
82 enum { k_iClientVRCallbacks = 4200 };
83 enum { k_iClientGameNotificationCallbacks = 4300 };
84 enum { k_iSteamGameNotificationCallbacks = 4400 };
85 enum { k_iSteamHTMLSurfaceCallbacks = 4500 };
86 enum { k_iClientVideoCallbacks = 4600 };
87 enum { k_iClientInventoryCallbacks = 4700 };
88 enum { k_iClientBluetoothManagerCallbacks = 4800 };
89 enum { k_iClientSharedConnectionCallbacks = 4900 };
90 enum { k_ISteamParentalSettingsCallbacks = 5000 };
91 enum { k_iClientShaderCallbacks = 5100 };
92 enum { k_iSteamGameSearchCallbacks = 5200 };
93 enum { k_iSteamPartiesCallbacks = 5300 };
94 enum { k_iClientPartiesCallbacks = 5400 };
95 enum { k_iSteamSTARCallbacks = 5500 };
96 enum { k_iClientSTARCallbacks = 5600 };
97 enum { k_iSteamRemotePlayCallbacks = 5700 };
98 enum { k_iClientCompatCallbacks = 5800 };
99 enum { k_iSteamChatCallbacks = 5900 };
100
101 // General result codes
102 typedef enum EResult
103 {
104 k_EResultNone = 0, // no result
105 k_EResultOK = 1, // success
106 k_EResultFail = 2, // generic failure
107 k_EResultNoConnection = 3, // no/failed network connection
108 // k_EResultNoConnectionRetry = 4, // OBSOLETE - removed
109 k_EResultInvalidPassword = 5, // password/ticket is invalid
110 k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere
111 k_EResultInvalidProtocolVer = 7, // protocol version is incorrect
112 k_EResultInvalidParam = 8, // a parameter is incorrect
113 k_EResultFileNotFound = 9, // file was not found
114 k_EResultBusy = 10, // called method busy - action not taken
115 k_EResultInvalidState = 11, // called object was in an invalid state
116 k_EResultInvalidName = 12, // name is invalid
117 k_EResultInvalidEmail = 13, // email is invalid
118 k_EResultDuplicateName = 14, // name is not unique
119 k_EResultAccessDenied = 15, // access is denied
120 k_EResultTimeout = 16, // operation timed out
121 k_EResultBanned = 17, // VAC2 banned
122 k_EResultAccountNotFound = 18, // account not found
123 k_EResultInvalidSteamID = 19, // steamID is invalid
124 k_EResultServiceUnavailable = 20, // The requested service is currently unavailable
125 k_EResultNotLoggedOn = 21, // The user is not logged on
126 k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party)
127 k_EResultEncryptionFailure = 23, // Encryption or Decryption failed
128 k_EResultInsufficientPrivilege = 24, // Insufficient privilege
129 k_EResultLimitExceeded = 25, // Too much of a good thing
130 k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes)
131 k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired
132 k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again
133 k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time
134 k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user
135 k_EResultIPNotFound = 31, // IP address not found
136 k_EResultPersistFailed = 32, // failed to write change to the data store
137 k_EResultLockingFailed = 33, // failed to acquire access lock for this operation
138 k_EResultLogonSessionReplaced = 34,
139 k_EResultConnectFailed = 35,
140 k_EResultHandshakeFailed = 36,
141 k_EResultIOFailure = 37,
142 k_EResultRemoteDisconnect = 38,
143 k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested
144 k_EResultBlocked = 40, // a user didn't allow it
145 k_EResultIgnored = 41, // target is ignoring sender
146 k_EResultNoMatch = 42, // nothing matching the request found
147 k_EResultAccountDisabled = 43,
148 k_EResultServiceReadOnly = 44, // this service is not accepting content changes right now
149 k_EResultAccountNotFeatured = 45, // account doesn't have value, so this feature isn't available
150 k_EResultAdministratorOK = 46, // allowed to take this action, but only because requester is admin
151 k_EResultContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol.
152 k_EResultTryAnotherCM = 48, // The current CM can't service the user making a request, user should try another.
153 k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed.
154 k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait
155 k_EResultSuspended = 51, // Long running operation (content download) suspended/paused
156 k_EResultCancelled = 52, // Operation canceled (typically by user: content download)
157 k_EResultDataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable
158 k_EResultDiskFull = 54, // Operation canceled - not enough disk space.
159 k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed
160 k_EResultPasswordUnset = 56, // Password could not be verified as it's unset server side
161 k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account
162 k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid
163 k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first
164 k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files
165 k_EResultIllegalPassword = 61, // The requested new password is not legal
166 k_EResultSameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer )
167 k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure
168 k_EResultCannotUseOldPassword = 64, // The requested new password is not legal
169 k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code invalid
170 k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent
171 k_EResultHardwareNotCapableOfIPT = 67, //
172 k_EResultIPTInitError = 68, //
173 k_EResultParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user
174 k_EResultFacebookQueryError = 70, // Facebook query returned an error
175 k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth code expired
176 k_EResultIPLoginRestrictionFailed = 72,
177 k_EResultAccountLockedDown = 73,
178 k_EResultAccountLogonDeniedVerifiedEmailRequired = 74,
179 k_EResultNoMatchingURL = 75,
180 k_EResultBadResponse = 76, // parse failure, missing field, etc.
181 k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password
182 k_EResultValueOutOfRange = 78, // the value entered is outside the acceptable range
183 k_EResultUnexpectedError = 79, // something happened that we didn't expect to ever happen
184 k_EResultDisabled = 80, // The requested service has been configured to be unavailable
185 k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid !
186 k_EResultRestrictedDevice = 82, // The device being used is not allowed to perform this action
187 k_EResultRegionLocked = 83, // The action could not be complete because it is region restricted
188 k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent
189 k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login
190 k_EResultItemDeleted = 86, // The thing we're trying to access has been deleted
191 k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker
192 k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch
193 k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match
194 k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners
195 k_EResultNotModified = 91, // data not modified
196 k_EResultNoMobileDevice = 92, // the account does not have a mobile device associated with it
197 k_EResultTimeNotSynced = 93, // the time presented is out of range or tolerance
198 k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.)
199 k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource
200 k_EResultAccountActivityLimitExceeded = 96, // Too many changes to this account
201 k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone
202 k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use wallet
203 k_EResultEmailSendFailure = 99, // Cannot send an email
204 k_EResultNotSettled = 100, // Can't perform operation till payment has settled
205 k_EResultNeedCaptcha = 101, // Needs to provide a valid captcha
206 k_EResultGSLTDenied = 102, // a game server login token owned by this token's owner has been banned
207 k_EResultGSOwnerDenied = 103, // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone)
208 k_EResultInvalidItemType = 104, // the type of thing we were requested to act on is invalid
209 k_EResultIPBanned = 105, // the ip address has been banned from taking this action
210 k_EResultGSLTExpired = 106, // this token has expired from disuse; can be reset for use
211 k_EResultInsufficientFunds = 107, // user doesn't have enough wallet funds to complete the action
212 k_EResultTooManyPending = 108, // There are too many of this thing pending already
213 k_EResultNoSiteLicensesFound = 109, // No site licenses found
214 k_EResultWGNetworkSendExceeded = 110, // the WG couldn't send a response because we exceeded max network send size
215 k_EResultAccountNotFriends = 111, // the user is not mutually friends
216 k_EResultLimitedUserAccount = 112, // the user is limited
217 k_EResultCantRemoveItem = 113, // item can't be removed
218 k_EResultAccountDeleted = 114, // account has been deleted
219 k_EResultExistingUserCancelledLicense = 115, // A license for this already exists, but cancelled
220 k_EResultCommunityCooldown = 116, // access is denied because of a community cooldown (probably from support profile data resets)
221 k_EResultNoLauncherSpecified = 117, // No launcher was specified, but a launcher was needed to choose correct realm for operation.
222 k_EResultMustAgreeToSSA = 118, // User must agree to china SSA or global SSA before login
223 k_EResultLauncherMigrated = 119, // The specified launcher type is no longer supported; the user should be directed elsewhere
224 k_EResultSteamRealmMismatch = 120, // The user's realm does not match the realm of the requested resource
225 k_EResultInvalidSignature = 121, // signature check did not match
226 k_EResultParseFailure = 122, // Failed to parse input
227 k_EResultNoVerifiedPhone = 123, // account does not have a verified phone number
228 } EResult;
229
230 // Structures
231 typedef struct {
232 u32 m_u32;
233 u64 m_u64;
234 u16 m_u16;
235 double m_d;
236 } ValvePackingSentinel_t;
237
238 typedef struct {
239
240 HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
241 int m_iCallback; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.)
242 u8 *m_pubParam; // Points to the callback structure
243 int m_cubParam; // Size of the data pointed to by m_pubParam
244
245 } CallbackMsg_t;
246
247 typedef struct {
248
249 SteamAPICall_t m_hAsyncCall;
250 int m_iCallback;
251 u32 m_cubParam;
252
253 } SteamAPICallCompleted_t;
254
255 // Steam universes. Each universe is a self-contained Steam instance.
256 typedef enum {
257 k_EUniverseInvalid = 0,
258 k_EUniversePublic = 1,
259 k_EUniverseBeta = 2,
260 k_EUniverseInternal = 3,
261 k_EUniverseDev = 4,
262 // k_EUniverseRC = 5, // no such universe anymore
263 k_EUniverseMax
264 } EUniverse_t;
265
266 typedef struct
267 {
268 // 64 bits total
269 union {
270 struct SteamIDComponent_t
271 {
272 #ifdef VALVE_BIG_ENDIAN
273 EUniverse_t m_EUniverse : 8; // universe this account belongs to
274 unsigned int m_EAccountType : 4; // type of account - can't show as EAccountType, due to signed / unsigned difference
275 unsigned int m_unAccountInstance : 20; // dynamic instance ID
276 u32 m_unAccountID : 32; // unique account identifier
277 #else
278 u32 m_unAccountID : 32; // unique account identifier
279 unsigned int m_unAccountInstance : 20; // dynamic instance ID
280 unsigned int m_EAccountType : 4; // type of account - can't show as EAccountType, due to signed / unsigned difference
281 EUniverse_t m_EUniverse : 8; // universe this account belongs to
282 #endif
283 } m_comp;
284
285 u64 m_unAll64Bits;
286 };
287 } CSteamID;
288
289 typedef struct GameID_t
290 {
291 #ifdef VALVE_BIG_ENDIAN
292 unsigned int m_nModID : 32;
293 unsigned int m_nType : 8;
294 unsigned int m_nAppID : 24;
295 #else
296 unsigned int m_nAppID : 24;
297 unsigned int m_nType : 8;
298 unsigned int m_nModID : 32;
299 #endif
300 } CGameID;
301
302 #define SW_CBID_SteamAPICallCompleted (k_iSteamUtilsCallbacks + 3)
303
304 typedef enum ESteamAPICallFailure
305 {
306 k_ESteamAPICallFailureNone = -1, // no failure
307 k_ESteamAPICallFailureSteamGone = 0, // the local Steam process has gone away
308 k_ESteamAPICallFailureNetworkFailure = 1, // the network connection to Steam has been broken, or was already broken
309 // SteamServersDisconnected_t callback will be sent around the same time
310 // SteamServersConnected_t will be sent when the client is able to talk to the Steam servers again
311 k_ESteamAPICallFailureInvalidHandle = 2, // the SteamAPICall_t handle passed in no longer exists
312 k_ESteamAPICallFailureMismatchedCallback = 3,// GetAPICallResult() was called with the wrong callback type for this API call
313 } ESteamAPICallFailure;
314
315 typedef u64 UGCHandle_t;
316 typedef u64 PublishedFileUpdateHandle_t;
317 typedef u64 PublishedFileId_t;
318 const PublishedFileId_t k_PublishedFileIdInvalid = 0;
319 const UGCHandle_t k_UGCHandleInvalid = 0xffffffffffffffffull;
320 const PublishedFileUpdateHandle_t k_PublishedFileUpdateHandleInvalid = 0xffffffffffffffffull;
321
322 // Handle for writing to Steam Cloud
323 typedef u64 UGCFileWriteStreamHandle_t;
324
325 // size limit on stat or achievement name (UTF-8 encoded)
326 enum { k_cchStatNameMax = 128 };
327
328 // maximum number of bytes for a leaderboard name (UTF-8 encoded)
329 enum { k_cchLeaderboardNameMax = 128 };
330
331 // maximum number of details i32's storable for a single leaderboard entry
332 enum { k_cLeaderboardDetailsMax = 64 };
333
334 // handle to a single leaderboard
335 typedef u64 SteamLeaderboard_t;
336
337 // handle to a set of downloaded entries in a leaderboard
338 typedef u64 SteamLeaderboardEntries_t;
339
340 // type of data request, when downloading leaderboard entries
341 typedef enum ELeaderboardDataRequest
342 {
343 k_ELeaderboardDataRequestGlobal = 0,
344 k_ELeaderboardDataRequestGlobalAroundUser = 1,
345 k_ELeaderboardDataRequestFriends = 2,
346 k_ELeaderboardDataRequestUsers = 3
347 } ELeaderboardDataRequest;
348
349 // the sort order of a leaderboard
350 typedef enum ELeaderboardSortMethod
351 {
352 k_ELeaderboardSortMethodNone = 0,
353 k_ELeaderboardSortMethodAscending = 1, // top-score is lowest number
354 k_ELeaderboardSortMethodDescending = 2, // top-score is highest number
355 } ELeaderboardSortMethod;
356
357 // the display type (used by the Steam Community web site) for a leaderboard
358 typedef enum ELeaderboardDisplayType
359 {
360 k_ELeaderboardDisplayTypeNone = 0,
361 k_ELeaderboardDisplayTypeNumeric = 1, // simple numerical score
362 k_ELeaderboardDisplayTypeTimeSeconds = 2, // the score represents a time, in seconds
363 k_ELeaderboardDisplayTypeTimeMilliSeconds = 3, // the score represents a time, in milliseconds
364 } ELeaderboardDisplayType;
365
366 typedef enum ELeaderboardUploadScoreMethod
367 {
368 k_ELeaderboardUploadScoreMethodNone = 0,
369 k_ELeaderboardUploadScoreMethodKeepBest = 1, // Leaderboard will keep user's best score
370 k_ELeaderboardUploadScoreMethodForceUpdate = 2, // Leaderboard will always replace score with specified
371 } ELeaderboardUploadScoreMethod;
372
373 // a single entry in a leaderboard, as returned by GetDownloadedLeaderboardEntry()
374 typedef struct LeaderboardEntry_t
375 {
376 CSteamID m_steamIDUser; // user with the entry - use SteamFriends()->GetFriendPersonaName() & SteamFriends()->GetFriendAvatar() to get more info
377 i32 m_nGlobalRank; // [1..N], where N is the number of users with an entry in the leaderboard
378 i32 m_nScore; // score as set in the leaderboard
379 i32 m_cDetails; // number of i32 details available for this entry
380 UGCHandle_t m_hUGC; // handle for UGC attached to the entry
381 } LeaderboardEntry_t;
382
383 //-----------------------------------------------------------------------------
384 // Purpose: called when the latests stats and achievements have been received
385 // from the server
386 //-----------------------------------------------------------------------------
387 typedef struct UserStatsReceived_t
388 {
389 u64 m_nGameID; // Game these stats are for
390 EResult m_eResult; // Success / error fetching the stats
391 CSteamID m_steamIDUser; // The user for whom the stats are retrieved for
392 } UserStatsReceived_t;
393 #define SW_CBID_UserStatsReceived (k_iSteamUserStatsCallbacks + 1)
394
395 //-----------------------------------------------------------------------------
396 // Purpose: result of a request to store the user stats for a game
397 //-----------------------------------------------------------------------------
398 typedef struct UserStatsStored_t
399 {
400 u64 m_nGameID; // Game these stats are for
401 EResult m_eResult; // success / error
402 } UserStatsStored_t;
403 #define SW_CBID_UserStatsStored (k_iSteamUserStatsCallbacks + 2)
404
405 //-----------------------------------------------------------------------------
406 // Purpose: result of a request to store the achievements for a game, or an
407 // "indicate progress" call. If both m_nCurProgress and m_nMaxProgress
408 // are zero, that means the achievement has been fully unlocked.
409 //-----------------------------------------------------------------------------
410 typedef struct UserAchievementStored_t
411 {
412 u64 m_nGameID; // Game this is for
413 int m_bGroupAchievement; // if this is a "group" achievement
414 char m_rgchAchievementName[k_cchStatNameMax]; // name of the achievement
415 u32 m_nCurProgress; // current progress towards the achievement
416 u32 m_nMaxProgress; // "out of" this many
417 } UserAchievementStored_t;
418 #define SW_CBID_UserAchievementStored (k_iSteamUserStatsCallbacks + 3)
419
420 //-----------------------------------------------------------------------------
421 // Purpose: call result for finding a leaderboard, returned as a result of FindOrCreateLeaderboard() or FindLeaderboard()
422 // use CCallResult<> to map this async result to a member function
423 //-----------------------------------------------------------------------------
424 typedef struct LeaderboardFindResult_t
425 {
426 SteamLeaderboard_t m_hSteamLeaderboard; // handle to the leaderboard serarched for, 0 if no leaderboard found
427 u8 m_bLeaderboardFound; // 0 if no leaderboard found
428 } LeaderboardFindResult_t;
429 #define SW_CBID_LeaderboardFindResult (k_iSteamUserStatsCallbacks + 4)
430
431 //-----------------------------------------------------------------------------
432 // Purpose: call result indicating scores for a leaderboard have been downloaded and are ready to be retrieved, returned as a result of DownloadLeaderboardEntries()
433 // use CCallResult<> to map this async result to a member function
434 //-----------------------------------------------------------------------------
435 typedef struct LeaderboardScoresDownloaded_t
436 {
437 SteamLeaderboard_t m_hSteamLeaderboard;
438 SteamLeaderboardEntries_t m_hSteamLeaderboardEntries; // the handle to pass into GetDownloadedLeaderboardEntries()
439 int m_cEntryCount; // the number of entries downloaded
440 } LeaderboardScoresDownloaded_t;
441 #define SW_CBID_LeaderboardScoresDownloaded (k_iSteamUserStatsCallbacks + 5)
442
443 //-----------------------------------------------------------------------------
444 // Purpose: call result indicating scores has been uploaded, returned as a result of UploadLeaderboardScore()
445 // use CCallResult<> to map this async result to a member function
446 //-----------------------------------------------------------------------------
447 typedef struct LeaderboardScoreUploaded_t
448 {
449 u8 m_bSuccess; // 1 if the call was successful
450 SteamLeaderboard_t m_hSteamLeaderboard; // the leaderboard handle that was
451 i32 m_nScore; // the score that was attempted to set
452 u8 m_bScoreChanged; // true if the score in the leaderboard change, false if the existing score was better
453 int m_nGlobalRankNew; // the new global rank of the user in this leaderboard
454 int m_nGlobalRankPrevious; // the previous global rank of the user in this leaderboard; 0 if the user had no existing entry in the leaderboard
455 } LeaderboardScoreUploaded_t;
456 #define SW_CBID_LeaderboardScoreUploaded (k_iSteamUserStatsCallbacks + 6)
457
458 typedef struct NumberOfCurrentPlayers_t
459 {
460 u8 m_bSuccess; // 1 if the call was successful
461 i32 m_cPlayers; // Number of players currently playing
462 } NumberOfCurrentPlayers_t;
463 #define SW_CBID_NumberOfCurrentPlayers (k_iSteamUserStatsCallbacks + 7)
464
465
466 //-----------------------------------------------------------------------------
467 // Purpose: Callback indicating that a user's stats have been unloaded.
468 // Call RequestUserStats again to access stats for this user
469 //-----------------------------------------------------------------------------
470 typedef struct UserStatsUnloaded_t
471 {
472 CSteamID m_steamIDUser; // User whose stats have been unloaded
473 } UserStatsUnloaded_t;
474 #define SW_CBID_UserStatsUnloaded (k_iSteamUserStatsCallbacks + 8)
475
476
477 //-----------------------------------------------------------------------------
478 // Purpose: Callback indicating that an achievement icon has been fetched
479 //-----------------------------------------------------------------------------
480 typedef struct UserAchievementIconFetched_t
481 {
482 CGameID m_nGameID; // Game this is for
483 char m_rgchAchievementName[k_cchStatNameMax]; // name of the achievement
484 int m_bAchieved; // Is the icon for the achieved or not achieved version?
485 int m_nIconHandle; // Handle to the image, which can be used in SteamUtils()->GetImageRGBA(), 0 means no image is set for the achievement
486 } UserAchievementIconFetched_t;
487 #define SW_CBID_UserAchievementIconFetched (k_iSteamUserStatsCallbacks + 9)
488
489 //-----------------------------------------------------------------------------
490 // Purpose: Callback indicating that global achievement percentages are fetched
491 //-----------------------------------------------------------------------------
492 typedef struct GlobalAchievementPercentagesReady_t
493 {
494 u64 m_nGameID; // Game this is for
495 EResult m_eResult; // Result of the operation
496 } GlobalAchievementPercentagesReady_t;
497 #define SW_CBID_GlobalAchievementPercentagesReady (k_iSteamUserStatsCallbacks + 10)
498
499 //-----------------------------------------------------------------------------
500 // Purpose: call result indicating UGC has been uploaded, returned as a result of SetLeaderboardUGC()
501 //-----------------------------------------------------------------------------
502 typedef struct LeaderboardUGCSet_t
503 {
504 EResult m_eResult; // The result of the operation
505 SteamLeaderboard_t m_hSteamLeaderboard; // the leaderboard handle that was
506 } LeaderboardUGCSet_t;
507 #define SW_CBID_LeaderboardUGCSet (k_iSteamUserStatsCallbacks + 11)
508
509 //-----------------------------------------------------------------------------
510 // Purpose: callback indicating that PS3 trophies have been installed
511 //-----------------------------------------------------------------------------
512 typedef struct PS3TrophiesInstalled_t
513 {
514 u64 m_nGameID; // Game these stats are for
515 EResult m_eResult; // The result of the operation
516 u64 m_ulRequiredDiskSpace; // If m_eResult is k_EResultDiskFull, will contain the amount of space needed to install trophies
517
518 } PS3TrophiesInstalled_t;
519 #define SW_CBID_TrophiesInstalled (k_iSteamUserStatsCallbacks + 12)
520
521 //-----------------------------------------------------------------------------
522 // Purpose: callback indicating global stats have been received.
523 // Returned as a result of RequestGlobalStats()
524 //-----------------------------------------------------------------------------
525 typedef struct GlobalStatsReceived_t
526 {
527 u64 m_nGameID; // Game global stats were requested for
528 EResult m_eResult; // The result of the request
529 } GlobalStatsReceived_t;
530 #define SW_CBID_GlobalStatsReceived (k_iSteamUserStatsCallbacks + 12)
531
532 #pragma pack( pop )
533
534 // API
535 void SteamAPI_Shutdown();
536 int SteamAPI_Init();
537 int SteamAPI_RestartAppIfNecessary( u32 unOwnAppID );
538
539 void SteamAPI_ManualDispatch_Init();
540 void SteamAPI_ManualDispatch_RunFrame( HSteamPipe hSteamPipe );
541 int SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe hSteamPipe, CallbackMsg_t *pCallbackMsg );
542 void SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe hSteamPipe );
543 int SteamAPI_ManualDispatch_GetAPICallResult( HSteamPipe hSteamPipe, SteamAPICall_t hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, int *pbFailed );
544 void SteamAPI_ReleaseCurrentThreadMemory();
545
546 int SteamAPI_ISteamUserStats_SetAchievement( ISteamUserStats *self, const char *pchName );
547
548 ESteamAPICallFailure SteamAPI_ISteamUtils_GetAPICallFailureReason( ISteamUtils* self, SteamAPICall_t hSteamAPICall );
549
550 // Friends
551 char *SteamAPI_ISteamFriends_GetPersonaName( ISteamFriends *self );
552 const char *SteamAPI_ISteamFriends_GetFriendPersonaName( ISteamFriends *self, u64_steamid steamIDFriend );
553 u64_steamid SteamAPI_ISteamUser_GetSteamID( ISteamUser *self );
554 int SteamAPI_ISteamFriends_GetSmallFriendAvatar( ISteamFriends *self, u64_steamid steamIDFriend ); // 32x32
555 int SteamAPI_ISteamUtils_GetImageSize( ISteamUtils *self, int iImage, u32 *pnWidth, u32 *pnHeight );
556 int SteamAPI_ISteamUtils_GetImageRGBA( ISteamUtils *self, int iImage, u8 *pubDest, int nDestBufferSize );
557
558 // Leaderboards
559 SteamAPICall_t SteamAPI_ISteamUserStats_FindOrCreateLeaderboard( ISteamUserStats* self, const char * pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType );
560 SteamAPICall_t SteamAPI_ISteamUserStats_FindLeaderboard( ISteamUserStats* self, const char * pchLeaderboardName );
561 const char * SteamAPI_ISteamUserStats_GetLeaderboardName( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard );
562 int SteamAPI_ISteamUserStats_GetLeaderboardEntryCount( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard );
563 ELeaderboardSortMethod SteamAPI_ISteamUserStats_GetLeaderboardSortMethod( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard );
564 ELeaderboardDisplayType SteamAPI_ISteamUserStats_GetLeaderboardDisplayType( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard );
565 SteamAPICall_t SteamAPI_ISteamUserStats_DownloadLeaderboardEntries( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardDataRequest eLeaderboardDataRequest, int nRangeStart, int nRangeEnd );
566 SteamAPICall_t SteamAPI_ISteamUserStats_DownloadLeaderboardEntriesForUsers( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard, CSteamID * prgUsers, int cUsers );
567 int SteamAPI_ISteamUserStats_GetDownloadedLeaderboardEntry( ISteamUserStats* self, SteamLeaderboardEntries_t hSteamLeaderboardEntries, int index, LeaderboardEntry_t * pLeaderboardEntry, i32 * pDetails, int cDetailsMax );
568 SteamAPICall_t SteamAPI_ISteamUserStats_UploadLeaderboardScore( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, i32 nScore, const i32 * pScoreDetails, int cScoreDetailsCount );
569 SteamAPICall_t SteamAPI_ISteamUserStats_AttachLeaderboardUGC( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC );
570
571 #define sw_get_image_size(...) SteamAPI_ISteamUtils_GetImageSize( steam_api_classes.utils, __VA_ARGS__ )
572 #define sw_get_image_rgba(...) SteamAPI_ISteamUtils_GetImageRGBA( steam_api_classes.utils, __VA_ARGS__ )
573 #define sw_get_small_friend_avatar(...) SteamAPI_ISteamFriends_GetSmallFriendAvatar( steam_api_classes.friends, __VA_ARGS__ )
574 #define sw_get_steamid() SteamAPI_ISteamUser_GetSteamID( steam_api_classes.friends )
575 #define sw_get_friend_persona_name(...) SteamAPI_ISteamFriends_GetFriendPersonaName( steam_api_classes.friends, __VA_ARGS__ )
576 #define sw_get_persona_name() SteamAPI_ISteamFriends_GetPersonaName( steam_api_classes.friends )
577 #define sw_find_leaderboard(...) SteamAPI_ISteamUserStats_FindLeaderboard( steam_api_classes.stats, __VA_ARGS__ );
578 #define sw_get_leaderboard_name(...) SteamAPI_ISteamUserStats_GetLeaderboardName( steam_api_classes.stats, __VA_ARGS__ )
579 #define sw_download_leaderboard_entries(...) SteamAPI_ISteamUserStats_DownloadLeaderboardEntries( steam_api_classes.stats, __VA_ARGS__ )
580 #define sw_get_downloaded_entry(...) SteamAPI_ISteamUserStats_GetDownloadedLeaderboardEntry( steam_api_classes.stats, __VA_ARGS__ )
581 #define sw_upload_leaderboard_score(...) SteamAPI_ISteamUserStats_UploadLeaderboardScore( steam_api_classes.stats, __VA_ARGS__ )
582
583 HSteamPipe SteamAPI_GetHSteamPipe();
584 HSteamUser SteamAPI_GetHSteamUser();
585
586 struct
587 {
588 ISteamFriends *friends;
589 ISteamUser *user;
590 ISteamUserStats *stats;
591 ISteamNetworking *net;
592 ISteamUtils *utils;
593
594 HSteamPipe pipe;
595
596 struct cached_player
597 {
598 u64_steamid id;
599 GLuint avatar_texture; // tex_unkown.name
600
601 struct cached_player *l, *r;
602 }
603 cached_players[20];
604
605 struct cached_player *cache_head, *cache_tail;
606
607 u32 cache_count;
608
609 } steam_api_classes;
610
611 static void _sw_cache_push( struct cached_player *player )
612 {
613 player->l = NULL;
614 player->r = steam_api_classes.cache_head;
615 if( steam_api_classes.cache_head ) steam_api_classes.cache_head->l = player;
616 if( !steam_api_classes.cache_tail ) steam_api_classes.cache_tail = player;
617 steam_api_classes.cache_head = player;
618 steam_api_classes.cache_count ++;
619 }
620
621 static void _sw_cache_evict( struct cached_player *player )
622 {
623 if( player == steam_api_classes.cache_tail ) steam_api_classes.cache_tail = player->l;
624 if( player == steam_api_classes.cache_head ) steam_api_classes.cache_head = player->r;
625 if( player->l ) player->l->r = player->r;
626 if( player->r ) player->r->l = player->l;
627 steam_api_classes.cache_count --;
628 }
629
630 static void _sw_access_cache( struct cached_player *player )
631 {
632 _sw_cache_evict( player );
633 _sw_cache_push( player );
634 }
635
636 static GLuint sw_get_player_image( u64_steamid usr )
637 {
638 #ifdef VG_STEAM
639
640 // Look for player in cache
641 for( int i = 0; i < steam_api_classes.cache_count; i ++ )
642 {
643 struct cached_player *player = &steam_api_classes.cached_players[i];
644
645 if( player->id == usr )
646 {
647 _sw_access_cache( player );
648 return player->avatar_texture;
649 }
650 }
651
652 struct cached_player *dest;
653
654 if( steam_api_classes.cache_count == vg_list_size( steam_api_classes.cached_players ) )
655 {
656 dest = steam_api_classes.cache_tail;
657 _sw_access_cache( dest );
658
659 // Delete previous before creating a new one
660 glDeleteTextures( 1, &dest->avatar_texture );
661 }
662 else
663 {
664 dest = &steam_api_classes.cached_players[ steam_api_classes.cache_count ];
665 _sw_cache_push( dest );
666 }
667
668 dest->id = usr;
669 dest->avatar_texture = 0;
670
671 // Upload new image
672 u32 x = 32, y = 32;
673 int steam_image;
674
675 steam_image = sw_get_small_friend_avatar( usr );
676 if( !steam_image )
677 return 0;
678
679 if( !sw_get_image_size( steam_image, &x, &y ) )
680 return 0;
681
682 u8 * img_buf = (u8 *)malloc( x * y * 4 );
683
684 if( !sw_get_image_rgba(steam_image, img_buf, x * y * 4) )
685 {
686 free( img_buf );
687 return 0;
688 }
689
690 glGenTextures( 1, &dest->avatar_texture );
691 glBindTexture( GL_TEXTURE_2D, dest->avatar_texture );
692
693 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_buf );
694 glGenerateMipmap( GL_TEXTURE_2D );
695
696 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
697 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
698
699 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
700 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
701
702 free( img_buf );
703
704 return dest->avatar_texture;
705
706 #else
707 return 0;
708 #endif
709 }
710
711 ISteamFriends *SteamAPI_SteamFriends_v017();
712 ISteamUser *SteamAPI_SteamUser_v021();
713 ISteamUserStats *SteamAPI_SteamUserStats_v012();
714 ISteamNetworking *SteamAPI_SteamNetworking_v006();
715 ISteamUtils *SteamAPI_SteamUtils_v010();
716
717 static void sw_exit(void)
718 {
719 #ifdef VG_STEAM
720 SteamAPI_Shutdown();
721 #endif
722 }
723
724 static void sw_free_opengl(void)
725 {
726 for( int i = 0; i < steam_api_classes.cache_count; i ++ )
727 if( steam_api_classes.cached_players[i].avatar_texture )
728 glDeleteTextures( 1, &steam_api_classes.cached_players[i].avatar_texture );
729 }
730
731 static int sw_init(void)
732 {
733 #ifdef VG_STEAM
734 #if defined(VALVE_CALLBACK_PACK_SMALL)
735 if( sizeof(ValvePackingSentinel_t) != 24 ){
736 printf( "Struct packing error: ValvePackingSentinel_t expected 24 got %i\nThe application is built incorrectly\n", (int)sizeof(ValvePackingSentinel_t));
737 return 0;
738 }
739 #else
740 if( sizeof(ValvePackingSentinel_t) != 32 ){
741 printf( "Struct packing error: ValvePackingSentinel_t expected 32 got %i\nThe application is built incorrectly\n", (int)sizeof(ValvePackingSentinel_t));
742 return 0;
743 }
744 #endif
745
746 vg_info( "Intializing steamworks\n" );
747
748 if( SteamAPI_RestartAppIfNecessary( VG_STEAM_APPID ) == 1 )
749 {
750 vg_info( "Restarting app via steam\n" );
751 return 0;
752 }
753
754 if( !SteamAPI_Init() )
755 {
756 vg_error( "Steamworks connection failed\n" );
757 return 0;
758 }
759
760 SteamAPI_ManualDispatch_Init();
761
762 steam_api_classes.friends = SteamAPI_SteamFriends_v017();
763 steam_api_classes.user = SteamAPI_SteamUser_v021();
764 steam_api_classes.stats = SteamAPI_SteamUserStats_v012();
765 steam_api_classes.net = SteamAPI_SteamNetworking_v006();
766 steam_api_classes.utils = SteamAPI_SteamUtils_v010();
767
768 if( !steam_api_classes.friends || !steam_api_classes.user || !steam_api_classes.stats || !steam_api_classes.net || !steam_api_classes.utils )
769 {
770 vg_error( "Steamworks interface pointers failed. Steamworks DLL may be old\n" );
771 SteamAPI_Shutdown();
772 return 0;
773 }
774
775 steam_api_classes.pipe = SteamAPI_GetHSteamPipe();
776 vg_success( "Steamworks API running\n" );
777
778 vg_register_exit( &sw_exit, "SteamAPI" );
779 return 1;
780 #else
781 return 1;
782 #endif
783 }
784
785
786 void (*sw_leaderboard_found)( LeaderboardFindResult_t *pCallback );
787 void (*sw_leaderboard_downloaded)( LeaderboardScoresDownloaded_t *pCallback );
788
789 static void sw_event_loop(void)
790 {
791 #ifdef VG_STEAM
792 SteamAPI_ManualDispatch_RunFrame( steam_api_classes.pipe );
793 CallbackMsg_t callback;
794
795 while( SteamAPI_ManualDispatch_GetNextCallback( steam_api_classes.pipe, &callback ) )
796 {
797 vg_info( "steamworks_event::callback( %i )\n", callback.m_iCallback );
798
799 // Check for dispatching API call results
800 if( callback.m_iCallback == SW_CBID_SteamAPICallCompleted ){
801
802 SteamAPICallCompleted_t *pCallCompleted = (SteamAPICallCompleted_t *)callback.m_pubParam;
803 void *pTmpCallResult = malloc( pCallCompleted->m_cubParam );
804 int bFailed;
805
806 if( SteamAPI_ManualDispatch_GetAPICallResult(
807 steam_api_classes.pipe,
808 pCallCompleted->m_hAsyncCall,
809 pTmpCallResult,
810 pCallCompleted->m_cubParam,
811 pCallCompleted->m_iCallback,
812 &bFailed )
813 )
814 {
815 // Dispatch the call result to the registered handler(s) for the
816 // call identified by pCallCompleted->m_hAsyncCall
817
818 vg_info( "steamworks_event::api_call_completed( %lu )\n", pCallCompleted->m_hAsyncCall );
819
820 switch( pCallCompleted->m_iCallback )
821 {
822 case SW_CBID_LeaderboardFindResult:
823 if( sw_leaderboard_found ) sw_leaderboard_found( (LeaderboardFindResult_t*)pTmpCallResult );
824 break;
825 case SW_CBID_LeaderboardScoresDownloaded:
826 if( sw_leaderboard_downloaded ) sw_leaderboard_downloaded( (LeaderboardScoresDownloaded_t*)pTmpCallResult );
827 break;
828 default:break;
829 }
830 }
831 else
832 {
833 typedef enum ESteamAPICallFailure
834 {
835 k_ESteamAPICallFailureNone = -1, // no failure
836 k_ESteamAPICallFailureSteamGone = 0, // the local Steam process has gone away
837 k_ESteamAPICallFailureNetworkFailure = 1, // the network connection to Steam has been broken, or was already broken
838 // SteamServersDisconnected_t callback will be sent around the same time
839 // SteamServersConnected_t will be sent when the client is able to talk to the Steam servers again
840 k_ESteamAPICallFailureInvalidHandle = 2, // the SteamAPICall_t handle passed in no longer exists
841 k_ESteamAPICallFailureMismatchedCallback = 3,// GetAPICallResult() was called with the wrong callback type for this API call
842 } ESteamAPICallFailure;
843
844 ESteamAPICallFailure fail_why =
845 SteamAPI_ISteamUtils_GetAPICallFailureReason( steam_api_classes.utils, pCallCompleted->m_hAsyncCall );
846
847 vg_error( "steamworks_event: error getting call result on %lu (code %d)\n", pCallCompleted->m_hAsyncCall, fail_why );
848 }
849
850 free( pTmpCallResult );
851 }
852 else
853 {
854 // Look at callback.m_iCallback to see what kind of callback it is,
855 // and dispatch to appropriate handler(s)
856 //void *data = callback.m_pubParam;
857
858 switch( callback.m_iCallback )
859 {
860 default: break;
861 }
862 }
863
864 SteamAPI_ManualDispatch_FreeLastCallback( steam_api_classes.pipe );
865 }
866 #endif
867 }
868
869 static void sw_set_achievement( const char *vg_ach_name )
870 {
871 struct vg_achievement *ach = NULL;
872
873 for( int i = 0; i < vg_list_size( vg_achievements ); i ++ )
874 if( !strcmp( vg_ach_name, vg_achievements[i].name ) )
875 ach = &vg_achievements[i];
876
877 if( !ach->is_set )
878 {
879 #ifdef VG_STEAM
880 SteamAPI_ISteamUserStats_SetAchievement( steam_api_classes.stats, vg_ach_name );
881 #endif
882 ach->is_set = 1;
883 vg_success( "Achievement set: '%s'\n", vg_ach_name );
884 }
885 }