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