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