clean flag
[vg.git] / vg_steam.h
1 #ifndef VG_STEAM_H
2 #define VG_STEAM_H
3
4 #include "vg.h"
5 #include "vg_log.h"
6
7 /*
8 * TODO: Combine interfaces and stuff here instead of having them in client code
9 */
10
11 #if defined(__linux__) || defined(__APPLE__)
12 /*
13 * The 32-bit version of gcc has the alignment requirement for u64 and double
14 * set to 4 meaning that even with #pragma pack(8) these types will only be
15 * four-byte aligned. The 64-bit version of gcc has the alignment requirement
16 * for these types set to 8 meaning that unless we use #pragma pack(4) our
17 * structures will get bigger. The 64-bit structure packing has to match the
18 * 32-bit structure packing for each platform.
19 */
20 #define VALVE_CALLBACK_PACK_SMALL
21 ;
22 #pragma pack( push, 4 )
23 #else
24 #define VALVE_CALLBACK_PACK_LARGE
25 #pragma pack( push, 8 )
26 #endif
27
28 typedef i32 HSteamPipe;
29 typedef i32 HSteamUser;
30
31 typedef int E_iCallBack_t;
32
33 typedef u64 u64_steamid;
34 typedef u64 SteamAPICall_t;
35
36 typedef u32 AppId_t;
37 const AppId_t k_uAppIdInvalid = 0x0;
38
39 typedef u32 DepotId_t;
40 const DepotId_t k_uDepotIdInvalid = 0x0;
41
42 typedef u32 RTime32;
43 typedef u32 AccountID_t;
44 typedef i8 steamapi_bool;
45
46 enum { k_iSteamUserCallbacks = 100 };
47 enum { k_iSteamGameServerCallbacks = 200 };
48 enum { k_iSteamFriendsCallbacks = 300 };
49 enum { k_iSteamBillingCallbacks = 400 };
50 enum { k_iSteamMatchmakingCallbacks = 500 };
51 enum { k_iSteamContentServerCallbacks = 600 };
52 enum { k_iSteamUtilsCallbacks = 700 };
53 enum { k_iClientFriendsCallbacks = 800 };
54 enum { k_iClientUserCallbacks = 900 };
55 enum { k_iSteamAppsCallbacks = 1000 };
56 enum { k_iSteamUserStatsCallbacks = 1100 };
57 enum { k_iSteamNetworkingCallbacks = 1200 };
58 enum { k_iSteamNetworkingSocketsCallbacks = 1220 };
59 enum { k_iSteamNetworkingMessagesCallbacks = 1250 };
60 enum { k_iSteamNetworkingUtilsCallbacks = 1280 };
61 enum { k_iSteamRemoteStorageCallbacks = 1300 };
62 enum { k_iClientDepotBuilderCallbacks = 1400 };
63 enum { k_iSteamGameServerItemsCallbacks = 1500 };
64 enum { k_iClientUtilsCallbacks = 1600 };
65 enum { k_iSteamGameCoordinatorCallbacks = 1700 };
66 enum { k_iSteamGameServerStatsCallbacks = 1800 };
67 enum { k_iSteam2AsyncCallbacks = 1900 };
68 enum { k_iSteamGameStatsCallbacks = 2000 };
69 enum { k_iClientHTTPCallbacks = 2100 };
70 enum { k_iClientScreenshotsCallbacks = 2200 };
71 enum { k_iSteamScreenshotsCallbacks = 2300 };
72 enum { k_iClientAudioCallbacks = 2400 };
73 enum { k_iClientUnifiedMessagesCallbacks = 2500 };
74 enum { k_iSteamStreamLauncherCallbacks = 2600 };
75 enum { k_iClientControllerCallbacks = 2700 };
76 enum { k_iSteamControllerCallbacks = 2800 };
77 enum { k_iClientParentalSettingsCallbacks = 2900 };
78 enum { k_iClientDeviceAuthCallbacks = 3000 };
79 enum { k_iClientNetworkDeviceManagerCallbacks = 3100 };
80 enum { k_iClientMusicCallbacks = 3200 };
81 enum { k_iClientRemoteClientManagerCallbacks = 3300 };
82 enum { k_iClientUGCCallbacks = 3400 };
83 enum { k_iSteamUGCCallbacks = 3400 };
84 enum { k_iSteamStreamClientCallbacks = 3500 };
85 enum { k_IClientProductBuilderCallbacks = 3600 };
86 enum { k_iClientShortcutsCallbacks = 3700 };
87 enum { k_iClientRemoteControlManagerCallbacks = 3800 };
88 enum { k_iSteamAppListCallbacks = 3900 };
89 enum { k_iSteamMusicCallbacks = 4000 };
90 enum { k_iSteamMusicRemoteCallbacks = 4100 };
91 enum { k_iClientVRCallbacks = 4200 };
92 enum { k_iClientGameNotificationCallbacks = 4300 };
93 enum { k_iSteamGameNotificationCallbacks = 4400 };
94 enum { k_iSteamHTMLSurfaceCallbacks = 4500 };
95 enum { k_iClientVideoCallbacks = 4600 };
96 enum { k_iClientInventoryCallbacks = 4700 };
97 enum { k_iClientBluetoothManagerCallbacks = 4800 };
98 enum { k_iClientSharedConnectionCallbacks = 4900 };
99 enum { k_ISteamParentalSettingsCallbacks = 5000 };
100 enum { k_iClientShaderCallbacks = 5100 };
101 enum { k_iSteamGameSearchCallbacks = 5200 };
102 enum { k_iSteamPartiesCallbacks = 5300 };
103 enum { k_iClientPartiesCallbacks = 5400 };
104 enum { k_iSteamSTARCallbacks = 5500 };
105 enum { k_iClientSTARCallbacks = 5600 };
106 enum { k_iSteamRemotePlayCallbacks = 5700 };
107 enum { k_iClientCompatCallbacks = 5800 };
108 enum { k_iSteamChatCallbacks = 5900 };
109
110 // General result codes
111 typedef enum EResult
112 {
113 k_EResultNone = 0, // no result
114 k_EResultOK = 1, // success
115 k_EResultFail = 2, // generic failure
116 k_EResultNoConnection = 3, // no/failed network connection
117 // k_EResultNoConnectionRetry = 4, // OBSOLETE - removed
118 k_EResultInvalidPassword = 5, // password/ticket is invalid
119 k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere
120 k_EResultInvalidProtocolVer = 7, // protocol version is incorrect
121 k_EResultInvalidParam = 8, // a parameter is incorrect
122 k_EResultFileNotFound = 9, // file was not found
123 k_EResultBusy = 10, // called method busy - action not taken
124 k_EResultInvalidState = 11, // called object was in an invalid state
125 k_EResultInvalidName = 12, // name is invalid
126 k_EResultInvalidEmail = 13, // email is invalid
127 k_EResultDuplicateName = 14, // name is not unique
128 k_EResultAccessDenied = 15, // access is denied
129 k_EResultTimeout = 16, // operation timed out
130 k_EResultBanned = 17, // VAC2 banned
131 k_EResultAccountNotFound = 18, // account not found
132 k_EResultInvalidSteamID = 19, // steamID is invalid
133 k_EResultServiceUnavailable = 20,// The requested service is currently
134 // unavailable
135 k_EResultNotLoggedOn = 21, // The user is not logged on
136 k_EResultPending = 22, // Request is pending (may be in process, or
137 // waiting on third party)
138 k_EResultEncryptionFailure = 23, // Encryption or Decryption failed
139 k_EResultInsufficientPrivilege = 24,// Insufficient privilege
140 k_EResultLimitExceeded = 25, // Too much of a good thing
141 k_EResultRevoked = 26, // Access has been revoked (used for revoked
142 // guest passes)
143 k_EResultExpired = 27, // License/Guest pass the user is trying to
144 // access is expired
145 k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by
146 // account, cannot be acked again
147 k_EResultDuplicateRequest = 29, // The request is a duplicate and the action
148 // has already occurred in the past, ignored
149 // this time
150 k_EResultAlreadyOwned = 30, // All the games in this guest pass
151 // redemption request are already owned by
152 // the user
153 k_EResultIPNotFound = 31, // IP address not found
154 k_EResultPersistFailed = 32, // failed to write change to the data store
155 k_EResultLockingFailed = 33, // failed to acquire access lock for this
156 // operation
157 k_EResultLogonSessionReplaced = 34,
158 k_EResultConnectFailed = 35,
159 k_EResultHandshakeFailed = 36,
160 k_EResultIOFailure = 37,
161 k_EResultRemoteDisconnect = 38,
162 k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart
163 // requested
164 k_EResultBlocked = 40, // a user didn't allow it
165 k_EResultIgnored = 41, // target is ignoring sender
166 k_EResultNoMatch = 42, // nothing matching the request found
167 k_EResultAccountDisabled = 43,
168 k_EResultServiceReadOnly = 44, // this service is not accepting content
169 // changes right now
170 k_EResultAccountNotFeatured = 45, // account doesn't have value, so this
171 // feature isn't available
172 k_EResultAdministratorOK = 46, // allowed to take this action, but only
173 // because requester is admin
174 k_EResultContentVersion = 47, // A Version mismatch in content
175 // transmitted within the Steam protocol.
176 k_EResultTryAnotherCM = 48, // The current CM can't service the user
177 // making a request, user should try
178 // another.
179 k_EResultPasswordRequiredToKickSession = 49, // You are already logged in
180 // elsewhere, this cached credential
181 // login has failed.
182 k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in
183 // elsewhere, you must wait
184 k_EResultSuspended = 51, // Long running operation (content download)
185 // suspended/paused
186 k_EResultCancelled = 52, // Operation canceled (typically by user:
187 // content download)
188 k_EResultDataCorruption = 53, // Operation canceled because data is ill
189 // formed or unrecoverable
190 k_EResultDiskFull = 54, // Operation canceled - not enough disk space.
191 k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed
192 k_EResultPasswordUnset = 56, // Password could not be verified as it's
193 // unset server side
194 k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...)
195 // is not linked to a Steam account
196 k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid
197 k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN,
198 // Facebook...) is already linked to some other account,
199 // must explicitly request to replace/delete the link first
200 k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict
201 // between the local and remote files
202 k_EResultIllegalPassword = 61, // The requested new password is not legal
203 k_EResultSameAsPreviousValue = 62,// new value is the same as the old one (
204 // secret question and answer )
205 k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor
206 // authentication failure
207 k_EResultCannotUseOldPassword = 64, // The requested new password is not
208 // legal
209 k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code
210 // invalid
211 k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd
212 // factor auth failure - and no mail
213 // has been sent
214 k_EResultHardwareNotCapableOfIPT = 67,
215 k_EResultIPTInitError = 68,
216 k_EResultParentalControlRestricted = 69,// operation failed due to parental
217 // control restrictions for current
218 // user
219 k_EResultFacebookQueryError = 70, // Facebook query returned an error
220 k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth
221 // code expired
222 k_EResultIPLoginRestrictionFailed = 72,
223 k_EResultAccountLockedDown = 73,
224 k_EResultAccountLogonDeniedVerifiedEmailRequired = 74,
225 k_EResultNoMatchingURL = 75,
226 k_EResultBadResponse = 76, // parse failure, missing field, etc.
227 k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action
228 // until they re-enter their password
229 k_EResultValueOutOfRange = 78, // the value entered is outside the
230 // acceptable range
231 k_EResultUnexpectedError = 79, // something happened that we didn't expect
232 // to ever happen
233 k_EResultDisabled = 80, // The requested service has been configured
234 // to be unavailable
235 k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG
236 // server are not valid !
237 k_EResultRestrictedDevice = 82, // The device being used is not allowed
238 // to perform this action
239 k_EResultRegionLocked = 83, // The action could not be complete
240 // because it is region restricted
241 k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try
242 // again later, different from
243 // k_EResultLimitExceeded which may be
244 // permanent
245 k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to
246 // login
247 k_EResultItemDeleted = 86, // The thing we're trying to access has been
248 // deleted
249 k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to
250 // throttle response to possible
251 // attacker
252 k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch
253 k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for
254 // two-factor didn't match
255 k_EResultAccountAssociatedToMultiplePartners = 90, // account has been
256 // associated with multiple partners
257 k_EResultNotModified = 91, // data not modified
258 k_EResultNoMobileDevice = 92, // the account does not have a mobile
259 // device associated with it
260 k_EResultTimeNotSynced = 93, // the time presented is out of range or
261 // tolerance
262 k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending,
263 // etc.)
264 k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource
265 k_EResultAccountActivityLimitExceeded = 96,// Too many changes to
266 // this account
267 k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone
268 k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use
269 // wallet
270 k_EResultEmailSendFailure = 99, // Cannot send an email
271 k_EResultNotSettled = 100, // Can't perform operation till payment
272 // has settled
273 k_EResultNeedCaptcha = 101,// Needs to provide a valid captcha
274 k_EResultGSLTDenied = 102, // a game server login token owned by this token's
275 // owner has been banned
276 k_EResultGSOwnerDenied = 103, // game server owner is denied for other reason
277 // (account lock, community ban, vac ban, missing phone)
278 k_EResultInvalidItemType = 104,// the type of thing we were requested to act
279 // on is invalid
280 k_EResultIPBanned = 105,// the ip address has been banned from taking this
281 // action
282 k_EResultGSLTExpired = 106,// this token has expired from disuse; can be
283 // reset for use
284 k_EResultInsufficientFunds = 107,// user doesn't have enough wallet funds to
285 // complete the action
286 k_EResultTooManyPending = 108, // There are too many of this thing pending
287 // already
288 k_EResultNoSiteLicensesFound = 109, // No site licenses found
289 k_EResultWGNetworkSendExceeded = 110,// the WG couldn't send a response
290 // because we exceeded max network send size
291 k_EResultAccountNotFriends = 111, // the user is not mutually friends
292 k_EResultLimitedUserAccount = 112,// the user is limited
293 k_EResultCantRemoveItem = 113, // item can't be removed
294 k_EResultAccountDeleted = 114, // account has been deleted
295 k_EResultExistingUserCancelledLicense = 115,
296 // A license for this already exists, but cancelled
297 k_EResultCommunityCooldown = 116, // access is denied because of a
298 // community cooldown (probably from support profile data resets)
299 k_EResultNoLauncherSpecified = 117, // No launcher was specified, but a
300 // launcher was needed to choose correct realm for operation.
301 k_EResultMustAgreeToSSA = 118,// User must agree to china SSA or global SSA
302 // before login
303 k_EResultLauncherMigrated = 119, // The specified launcher type is no longer
304 // supported; the user should be directed elsewhere
305 k_EResultSteamRealmMismatch = 120, // The user's realm does not match the
306 // realm of the requested resource
307 k_EResultInvalidSignature = 121, // signature check did not match
308 k_EResultParseFailure = 122, // Failed to parse input
309 k_EResultNoVerifiedPhone = 123, // account does not have a verified phone
310 // number
311 } EResult;
312
313 typedef struct {
314
315 HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
316 int m_iCallback;
317 u8 *m_pubParam; // Points to the callback structure
318 int m_cubParam; // Size of the data pointed to by m_pubParam
319
320 } CallbackMsg_t;
321
322 typedef struct {
323
324 SteamAPICall_t m_hAsyncCall;
325 int m_iCallback;
326 u32 m_cubParam;
327
328 } SteamAPICallCompleted_t;
329 enum { k_iSteamAPICallCompleted = k_iSteamUtilsCallbacks + 3 };
330
331 // Steam universes. Each universe is a self-contained Steam instance.
332 typedef enum EUniverse {
333 k_EUniverseInvalid = 0,
334 k_EUniversePublic = 1,
335 k_EUniverseBeta = 2,
336 k_EUniverseInternal = 3,
337 k_EUniverseDev = 4,
338 // k_EUniverseRC = 5, // no such universe anymore
339 k_EUniverseMax
340 } EUniverse_t;
341
342 #pragma pack( push, 1 )
343 struct SteamIDComponent_t
344 {
345 #ifdef VALVE_BIG_ENDIAN
346 EUniverse_t m_EUniverse : 8
347 unsigned int m_EAccountType : 4;
348 unsigned int m_unAccountInstance : 20;
349 u32 m_unAccountID : 32;
350 #else
351 u32 m_unAccountID : 32;
352 unsigned int m_unAccountInstance : 20;
353 unsigned int m_EAccountType : 4;
354 EUniverse_t m_EUniverse : 8;
355 #endif
356 };
357
358 typedef struct
359 {
360 // 64 bits total
361 union
362 {
363 struct SteamIDComponent_t m_comp;
364 u64 m_unAll64Bits;
365 };
366 }
367 CSteamID;
368
369 typedef struct GameID_t
370 {
371 #ifdef VALVE_BIG_ENDIAN
372 unsigned int m_nModID : 32;
373 unsigned int m_nType : 8;
374 unsigned int m_nAppID : 24;
375 #else
376 unsigned int m_nAppID : 24;
377 unsigned int m_nType : 8;
378 unsigned int m_nModID : 32;
379 #endif
380 } CGameID;
381 #pragma pack( pop )
382 #pragma pack( pop )
383
384 /*
385 * Standard login
386 * =============================================================================
387 */
388
389 int SteamAPI_RestartAppIfNecessary( u32 unOwnAppID );
390 int SteamAPI_Init(void);
391 void SteamAPI_Shutdown(void);
392
393 /*
394 * Server mode login
395 * =============================================================================
396 */
397
398 typedef enum EServerMode EServerMode;
399 enum EServerMode
400 {
401 eServerModeInvalid = 0,
402 eServerModeNoAuthentication = 1,
403 eServerModeAuthentication = 2,
404 eServerModeAuthenticationAndSecure = 3,
405 };
406
407 int SteamInternal_GameServer_Init( u32 unIP, u16 usLegacySteamPort,
408 u16 usGamePort, u16 usQueryPort,
409 EServerMode eServerMode,
410 const char *pchVersionString );
411
412 /* Initialize SteamGameServer client and interface objects, and set server
413 * properties which may not be changed.
414 * After calling this function, you should set any additional server parameters,
415 * and then call ISteamGameServer::LogOnAnonymous() or ISteamGameServer::LogOn()
416 *
417 * - unIP will usually be zero. If you are on a machine with multiple IP
418 * addresses, you can pass a non-zero value here and the relevant sockets will
419 * be bound to that IP. This can be used to ensure that the IP you desire is
420 * the one used in the server browser.
421 * - usGamePort is the port that clients will connect to for gameplay. You will
422 * usually open up your own socket bound to this port.
423 * - usQueryPort is the port that will manage server browser related duties and
424 * info pings from clients. If you pass STEAMGAMESERVER_QUERY_PORT_SHARED for
425 * usQueryPort, then it will use "GameSocketShare" mode, which means that the
426 * game is responsible for sending and receiving UDP packets for the master
427 * server updater. (See ISteamGameServer::HandleIncomingPacket and
428 * ISteamGameServer::GetNextOutgoingPacket.)
429 * - The version string should be in the form x.x.x.x, and is used by the master
430 * server to detect when the server is out of date. (Only servers with the
431 * latest version will be listed.)
432 */
433 int SteamGameServer_Init( u32 unIP, u16 usGamePort, u16 usQueryPort,
434 EServerMode eServerMode,
435 const char *pchVersionString )
436 {
437 return SteamInternal_GameServer_Init( unIP, 0, usGamePort, usQueryPort,
438 eServerMode, pchVersionString );
439 }
440
441
442 void *SteamAPI_SteamGameServer_v014(void);
443 void *SteamAPI_SteamGameServer(void)
444 {
445 return SteamAPI_SteamGameServer_v014();
446 }
447
448 void SteamAPI_ISteamGameServer_LogOnAnonymous( void* self );
449
450 void SteamGameServer_Shutdown(void);
451
452 int SteamGameServer_BSecure(void);
453 u64 SteamGameServer_GetSteamID(void);
454
455 /*
456 * Async callbacks
457 * =============================================================================
458 */
459
460 typedef struct vg_steam_async_call vg_steam_async_call;
461 typedef struct vg_steam_callback_handler vg_steam_callback_handler;
462
463 struct vg_steam{
464 struct vg_steam_async_call{
465 SteamAPICall_t id;
466 void *userdata;
467
468 void (*p_handler)( void *result, void *userdata );
469 }
470 calls[4];
471 u32 call_count;
472
473 struct vg_steam_callback_handler{
474 u32 callback_id;
475 void (*p_handler)( CallbackMsg_t *msg );
476 }
477 callback_handlers[32];
478 u32 callback_handler_count;
479 }
480 static vg_steam;
481
482 vg_steam_async_call *vg_alloc_async_steam_api_call(void)
483 {
484 if( vg_steam.call_count == vg_list_size(vg_steam.calls) ){
485 vg_fatal_error( "Maximum concurrent API calls exceeded (%u)\n",
486 vg_steam.call_count );
487 }
488
489 return &vg_steam.calls[ vg_steam.call_count ++ ];
490 }
491
492 /*
493 * Regular callbacks
494 * =============================================================================
495 */
496
497 static void steam_register_callback( u32 id,
498 void (*p_handler)( CallbackMsg_t *msg ) )
499 {
500 if( vg_steam.callback_handler_count ==
501 vg_list_size(vg_steam.callback_handlers) )
502 {
503 vg_fatal_error( "Too many steam callback handlers registered (%u)\n",
504 vg_steam.callback_handler_count );
505 }
506
507 vg_steam_callback_handler *handler =
508 &vg_steam.callback_handlers[ vg_steam.callback_handler_count ++ ];
509
510 handler->p_handler = p_handler;
511 handler->callback_id = id;
512 }
513
514 /*
515 * Event loop
516 * =============================================================================
517 */
518 HSteamPipe SteamAPI_GetHSteamPipe(void);
519 HSteamPipe SteamGameServer_GetHSteamPipe(void);
520 HSteamUser SteamAPI_GetHSteamUser(void);
521 void SteamAPI_ManualDispatch_Init(void);
522 void SteamAPI_ManualDispatch_RunFrame( HSteamPipe hSteamPipe );
523 steamapi_bool SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe hSteamPipe,
524 CallbackMsg_t *pCallbackMsg );
525 void SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe hSteamPipe );
526 steamapi_bool SteamAPI_ManualDispatch_GetAPICallResult( HSteamPipe hSteamPipe,
527 SteamAPICall_t hSteamAPICall, void *pCallback, int cubCallback,
528 int iCallbackExpected, steamapi_bool *pbFailed );
529
530 void SteamAPI_ReleaseCurrentThreadMemory(void);
531
532 static void steamworks_process_api_call( HSteamPipe pipe,
533 CallbackMsg_t *callback )
534 {
535 SteamAPICallCompleted_t *pCallCompleted =
536 (SteamAPICallCompleted_t *)callback->m_pubParam;
537
538 steamapi_bool bFailed;
539 void *call_data = alloca( pCallCompleted->m_cubParam );
540
541 if( SteamAPI_ManualDispatch_GetAPICallResult(
542 pipe,
543 pCallCompleted->m_hAsyncCall,
544 call_data,
545 pCallCompleted->m_cubParam,
546 pCallCompleted->m_iCallback,
547 &bFailed )
548 )
549 {
550 /*
551 * Dispatch the call result to the registered handler(s) for the
552 * call identified by pCallCompleted->m_hAsyncCall
553 */
554
555 vg_info( "steamworks_event::api_call_completed( %lu )\n",
556 pCallCompleted->m_hAsyncCall );
557
558 int j=0;
559 for( int i=0; i<vg_steam.call_count; i++ ){
560 if( vg_steam.calls[i].id != pCallCompleted->m_hAsyncCall ){
561 vg_steam.calls[j ++] = vg_steam.calls[i];
562 }
563 else{
564 vg_steam_async_call *call = &vg_steam.calls[i];
565 call->p_handler( call_data, call->userdata );
566 }
567 }
568
569 if( vg_steam.call_count == j ){
570 vg_error( "No tracker was register for API call\n" );
571 }
572
573 vg_steam.call_count = j;
574 }
575 else
576 {
577 #if 0
578 typedef enum ESteamAPICallFailure
579 {
580 k_ESteamAPICallFailureNone = -1,
581 k_ESteamAPICallFailureSteamGone = 0,
582 k_ESteamAPICallFailureNetworkFailure = 1,
583 k_ESteamAPICallFailureInvalidHandle = 2,
584 k_ESteamAPICallFailureMismatchedCallback = 3,
585 }
586
587 ESteamAPICallFailure;
588 ESteamAPICallFailure fail_why =
589 SteamAPI_ISteamUtils_GetAPICallFailureReason(
590 steam_api_classes.utils, pCallCompleted->m_hAsyncCall );
591
592 vg_error( "steamworks_event: error getting call result on"
593 "%lu (code %d)\n",
594 pCallCompleted->m_hAsyncCall, fail_why );
595 #endif
596 }
597 }
598
599 static void steamworks_event_loop( HSteamPipe pipe )
600 {
601 SteamAPI_ManualDispatch_RunFrame( pipe );
602 CallbackMsg_t callback;
603
604 while( SteamAPI_ManualDispatch_GetNextCallback( pipe, &callback ) ){
605 vg_low( "steamworks_event::callback( %i )\n", callback.m_iCallback );
606
607 /* Check for dispatching API call results */
608 if( callback.m_iCallback == k_iSteamAPICallCompleted ){
609 steamworks_process_api_call( pipe, &callback );
610 }
611 else {
612 /*
613 * Look at callback.m_iCallback to see what kind of callback it is,
614 * and dispatch to appropriate handler(s)
615 * void *data = callback.m_pubParam;
616 */
617
618 for( int i=0; i<vg_steam.callback_handler_count; i++ ){
619 vg_steam_callback_handler *handler = &vg_steam.callback_handlers[i];
620 if( handler->callback_id == callback.m_iCallback ){
621 handler->p_handler( &callback );
622 break;
623 }
624 }
625 }
626
627 SteamAPI_ManualDispatch_FreeLastCallback( pipe );
628 }
629 }
630
631 /*
632 * This is required to run the server outside of steamcmd environment.
633 * It can be any appid but idealy the one that is actually your game
634 */
635 static void steamworks_ensure_txt( const char *appid_str )
636 {
637 FILE *txt = fopen("steam_appid.txt", "w");
638 fputs( appid_str, txt );
639 fclose( txt );
640 }
641
642 #endif /* VG_STEAM_H */