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