//====== Copyright Valve Corporation, All rights reserved. ==================== // // Internal implementation details of the steamworks SDK. // // You should be able to figure out how to use the SDK by reading // steam_api_common.h, and should not need to understand anything in here. // //----------------------------------------------------------------------------- #ifdef STEAM_CALLBACK_BEGIN #error "This file should only be included from steam_api_common.h" #endif #include // Internal functions used by the utility CCallback objects to receive callbacks S_API void S_CALLTYPE SteamAPI_RegisterCallback( class CCallbackBase *pCallback, int iCallback ); S_API void S_CALLTYPE SteamAPI_UnregisterCallback( class CCallbackBase *pCallback ); // Internal functions used by the utility CCallResult objects to receive async call results S_API void S_CALLTYPE SteamAPI_RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall ); S_API void S_CALLTYPE SteamAPI_UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall ); S_API HSteamPipe S_CALLTYPE SteamAPI_GetHSteamPipe(); S_API HSteamUser S_CALLTYPE SteamAPI_GetHSteamUser(); S_API HSteamPipe S_CALLTYPE SteamGameServer_GetHSteamPipe(); S_API HSteamUser S_CALLTYPE SteamGameServer_GetHSteamUser(); S_API void *S_CALLTYPE SteamInternal_ContextInit( void *pContextInitData ); S_API void *S_CALLTYPE SteamInternal_CreateInterface( const char *ver ); S_API void *S_CALLTYPE SteamInternal_FindOrCreateUserInterface( HSteamUser hSteamUser, const char *pszVersion ); S_API void *S_CALLTYPE SteamInternal_FindOrCreateGameServerInterface( HSteamUser hSteamUser, const char *pszVersion ); // disable this warning; this pattern need for steam callback registration #ifdef _MSVC_VER #pragma warning( push ) #pragma warning( disable: 4355 ) // 'this' : used in base member initializer list #endif #define _STEAM_CALLBACK_AUTO_HOOK( thisclass, func, param ) #define _STEAM_CALLBACK_HELPER( _1, _2, SELECTED, ... ) _STEAM_CALLBACK_##SELECTED #define _STEAM_CALLBACK_SELECT( X, Y ) _STEAM_CALLBACK_HELPER X Y #define _STEAM_CALLBACK_3( extra_code, thisclass, func, param ) \ struct CCallbackInternal_ ## func : private CCallbackImpl< sizeof( param ) > { \ CCallbackInternal_ ## func () { extra_code SteamAPI_RegisterCallback( this, param::k_iCallback ); } \ CCallbackInternal_ ## func ( const CCallbackInternal_ ## func & ) { extra_code SteamAPI_RegisterCallback( this, param::k_iCallback ); } \ CCallbackInternal_ ## func & operator=( const CCallbackInternal_ ## func & ) { return *this; } \ private: virtual void Run( void *pvParam ) { _STEAM_CALLBACK_AUTO_HOOK( thisclass, func, param ) \ thisclass *pOuter = reinterpret_cast( reinterpret_cast(this) - offsetof( thisclass, m_steamcallback_ ## func ) ); \ pOuter->func( reinterpret_cast( pvParam ) ); \ } \ } m_steamcallback_ ## func ; void func( param *pParam ) #define _STEAM_CALLBACK_4( _, thisclass, func, param, var ) \ CCallback< thisclass, param > var; void func( param *pParam ) #define _STEAM_CALLBACK_GS( _, thisclass, func, param, var ) \ CCallback< thisclass, param, true > var; void func( param *pParam ) template< class T, class P > inline CCallResult::CCallResult() { m_hAPICall = k_uAPICallInvalid; m_pObj = nullptr; m_Func = nullptr; m_iCallback = P::k_iCallback; } template< class T, class P > inline void CCallResult::Set( SteamAPICall_t hAPICall, T *p, func_t func ) { if ( m_hAPICall ) SteamAPI_UnregisterCallResult( this, m_hAPICall ); m_hAPICall = hAPICall; m_pObj = p; m_Func = func; if ( hAPICall ) SteamAPI_RegisterCallResult( this, hAPICall ); } template< class T, class P > inline bool CCallResult::IsActive() const { return (m_hAPICall != k_uAPICallInvalid); } template< class T, class P > inline void CCallResult::Cancel() { if ( m_hAPICall != k_uAPICallInvalid ) { SteamAPI_UnregisterCallResult( this, m_hAPICall ); m_hAPICall = k_uAPICallInvalid; } } template< class T, class P > inline CCallResult::~CCallResult() { Cancel(); } template< class T, class P > inline void CCallResult::Run( void *pvParam ) { m_hAPICall = k_uAPICallInvalid; // caller unregisters for us (m_pObj->*m_Func)((P *)pvParam, false); } template< class T, class P > inline void CCallResult::Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ) { if ( hSteamAPICall == m_hAPICall ) { m_hAPICall = k_uAPICallInvalid; // caller unregisters for us (m_pObj->*m_Func)((P *)pvParam, bIOFailure); } } template< class T, class P, bool bGameserver > inline CCallback< T, P, bGameserver >::CCallback( T *pObj, func_t func ) : m_pObj( nullptr ), m_Func( nullptr ) { if ( bGameserver ) { this->SetGameserverFlag(); } Register( pObj, func ); } template< class T, class P, bool bGameserver > inline void CCallback< T, P, bGameserver >::Register( T *pObj, func_t func ) { if ( !pObj || !func ) return; if ( this->m_nCallbackFlags & CCallbackBase::k_ECallbackFlagsRegistered ) Unregister(); m_pObj = pObj; m_Func = func; // SteamAPI_RegisterCallback sets k_ECallbackFlagsRegistered SteamAPI_RegisterCallback( this, P::k_iCallback ); } template< class T, class P, bool bGameserver > inline void CCallback< T, P, bGameserver >::Unregister() { // SteamAPI_UnregisterCallback removes k_ECallbackFlagsRegistered SteamAPI_UnregisterCallback( this ); } template< class T, class P, bool bGameserver > inline void CCallback< T, P, bGameserver >::Run( void *pvParam ) { (m_pObj->*m_Func)((P *)pvParam); } //----------------------------------------------------------------------------- // Macros to define steam callback structures. Used internally for debugging //----------------------------------------------------------------------------- #ifdef STEAM_CALLBACK_INSPECTION_ENABLED #include "../../clientdll/steam_api_callback_inspection.h" #else #define STEAM_CALLBACK_BEGIN( callbackname, callbackid ) struct callbackname { enum { k_iCallback = callbackid }; #define STEAM_CALLBACK_MEMBER( varidx, vartype, varname ) vartype varname ; #define STEAM_CALLBACK_MEMBER_ARRAY( varidx, vartype, varname, varcount ) vartype varname [ varcount ]; #define STEAM_CALLBACK_END(nArgs) }; #endif // Forward declare all of the Steam interfaces. (Do we really need to do this?) class ISteamClient; class ISteamUser; class ISteamGameServer; class ISteamFriends; class ISteamUtils; class ISteamMatchmaking; class ISteamContentServer; class ISteamMatchmakingServers; class ISteamUserStats; class ISteamApps; class ISteamNetworking; class ISteamRemoteStorage; class ISteamScreenshots; class ISteamMusic; class ISteamMusicRemote; class ISteamGameServerStats; class ISteamPS3OverlayRender; class ISteamHTTP; class ISteamController; class ISteamUGC; class ISteamAppList; class ISteamHTMLSurface; class ISteamInventory; class ISteamVideo; class ISteamParentalSettings; class ISteamGameSearch; class ISteamInput; class ISteamParties; class ISteamTV; class ISteamRemotePlay; //----------------------------------------------------------------------------- // Purpose: Base values for callback identifiers, each callback must // have a unique ID. //----------------------------------------------------------------------------- enum { k_iSteamUserCallbacks = 100 }; enum { k_iSteamGameServerCallbacks = 200 }; enum { k_iSteamFriendsCallbacks = 300 }; enum { k_iSteamBillingCallbacks = 400 }; enum { k_iSteamMatchmakingCallbacks = 500 }; enum { k_iSteamContentServerCallbacks = 600 }; enum { k_iSteamUtilsCallbacks = 700 }; enum { k_iClientFriendsCallbacks = 800 }; enum { k_iClientUserCallbacks = 900 }; enum { k_iSteamAppsCallbacks = 1000 }; enum { k_iSteamUserStatsCallbacks = 1100 }; enum { k_iSteamNetworkingCallbacks = 1200 }; enum { k_iSteamNetworkingSocketsCallbacks = 1220 }; enum { k_iSteamNetworkingMessagesCallbacks = 1250 }; enum { k_iSteamNetworkingUtilsCallbacks = 1280 }; enum { k_iClientRemoteStorageCallbacks = 1300 }; enum { k_iClientDepotBuilderCallbacks = 1400 }; enum { k_iSteamGameServerItemsCallbacks = 1500 }; enum { k_iClientUtilsCallbacks = 1600 }; enum { k_iSteamGameCoordinatorCallbacks = 1700 }; enum { k_iSteamGameServerStatsCallbacks = 1800 }; enum { k_iSteam2AsyncCallbacks = 1900 }; enum { k_iSteamGameStatsCallbacks = 2000 }; enum { k_iClientHTTPCallbacks = 2100 }; enum { k_iClientScreenshotsCallbacks = 2200 }; enum { k_iSteamScreenshotsCallbacks = 2300 }; enum { k_iClientAudioCallbacks = 2400 }; enum { k_iClientUnifiedMessagesCallbacks = 2500 }; enum { k_iSteamStreamLauncherCallbacks = 2600 }; enum { k_iClientControllerCallbacks = 2700 }; enum { k_iSteamControllerCallbacks = 2800 }; enum { k_iClientParentalSettingsCallbacks = 2900 }; enum { k_iClientDeviceAuthCallbacks = 3000 }; enum { k_iClientNetworkDeviceManagerCallbacks = 3100 }; enum { k_iClientMusicCallbacks = 3200 }; enum { k_iClientRemoteClientManagerCallbacks = 3300 }; enum { k_iClientUGCCallbacks = 3400 }; enum { k_iSteamStreamClientCallbacks = 3500 }; enum { k_IClientProductBuilderCallbacks = 3600 }; enum { k_iClientShortcutsCallbacks = 3700 }; enum { k_iClientRemoteControlManagerCallbacks = 3800 }; enum { k_iSteamAppListCallbacks = 3900 }; enum { k_iSteamMusicCallbacks = 4000 }; enum { k_iSteamMusicRemoteCallbacks = 4100 }; enum { k_iClientVRCallbacks = 4200 }; enum { k_iClientGameNotificationCallbacks = 4300 }; enum { k_iSteamGameNotificationCallbacks = 4400 }; enum { k_iSteamHTMLSurfaceCallbacks = 4500 }; enum { k_iClientVideoCallbacks = 4600 }; enum { k_iClientInventoryCallbacks = 4700 }; enum { k_iClientBluetoothManagerCallbacks = 4800 }; enum { k_iClientSharedConnectionCallbacks = 4900 }; enum { k_ISteamParentalSettingsCallbacks = 5000 }; enum { k_iClientShaderCallbacks = 5100 }; enum { k_iSteamGameSearchCallbacks = 5200 }; enum { k_iSteamPartiesCallbacks = 5300 }; enum { k_iClientPartiesCallbacks = 5400 }; enum { k_iSteamSTARCallbacks = 5500 }; enum { k_iClientSTARCallbacks = 5600 }; enum { k_iSteamRemotePlayCallbacks = 5700 }; // Macro used to define a type-safe accessor that will always return the version // of the interface of the *header file* you are compiling with! We also bounce // through a safety function that checks for interfaces being created or destroyed. #ifndef STEAM_API_EXPORTS // SteamInternal_ContextInit takes a base pointer for the equivalent of // struct { void (*pFn)(void* pCtx); uintp counter; CSteamAPIContext ctx; } // Do not change layout of 2 + sizeof... or add non-pointer aligned data! // NOTE: declaring "static CSteamAPIConext" creates a large function // which queries the initialization status of the object. We know that // it is pointer-aligned and fully memset with zeros, so just alias a // static buffer of the appropriate size and call it a CSteamAPIContext. #define STEAM_DEFINE_INTERFACE_ACCESSOR( type, name, expr ) \ inline void S_CALLTYPE SteamInternal_Init_ ## name( type *p ) { *p = (type)( expr ); } \ inline type name() { \ static void* s_CallbackCounterAndContext[ 3 ] = { (void*)&SteamInternal_Init_ ## name, 0, 0 }; \ return *(type*)SteamInternal_ContextInit( s_CallbackCounterAndContext ); \ } #else // Stub when we're compiling steam_api.dll itself. These are inline // functions defined when the header is included. not functions exported // by the lib! #define STEAM_DEFINE_INTERFACE_ACCESSOR( type, name, expr ) #endif #define STEAM_DEFINE_USER_INTERFACE_ACCESSOR( type, name, version ) \ STEAM_DEFINE_INTERFACE_ACCESSOR( type, name, SteamInternal_FindOrCreateUserInterface( SteamAPI_GetHSteamUser(), version ) ) #define STEAM_DEFINE_GAMESERVER_INTERFACE_ACCESSOR( type, name, version ) \ STEAM_DEFINE_INTERFACE_ACCESSOR( type, name, SteamInternal_FindOrCreateGameServerInterface( SteamGameServer_GetHSteamUser(), version ) ) #ifdef _MSVC_VER #pragma warning( pop ) #endif // CSteamAPIContext encapsulates the Steamworks API global accessors into // a single object. // // DEPRECATED: Used the global interface accessors instead! // // This will be removed in a future iteration of the SDK class CSteamAPIContext { public: CSteamAPIContext() { Clear(); } inline void Clear() { memset( this, 0, sizeof(*this) ); } inline bool Init(); // NOTE: This is defined in steam_api.h, to avoid this file having to include everything ISteamClient* SteamClient() const { return m_pSteamClient; } ISteamUser* SteamUser() const { return m_pSteamUser; } ISteamFriends* SteamFriends() const { return m_pSteamFriends; } ISteamUtils* SteamUtils() const { return m_pSteamUtils; } ISteamMatchmaking* SteamMatchmaking() const { return m_pSteamMatchmaking; } ISteamGameSearch* SteamGameSearch() const { return m_pSteamGameSearch; } ISteamUserStats* SteamUserStats() const { return m_pSteamUserStats; } ISteamApps* SteamApps() const { return m_pSteamApps; } ISteamMatchmakingServers* SteamMatchmakingServers() const { return m_pSteamMatchmakingServers; } ISteamNetworking* SteamNetworking() const { return m_pSteamNetworking; } ISteamRemoteStorage* SteamRemoteStorage() const { return m_pSteamRemoteStorage; } ISteamScreenshots* SteamScreenshots() const { return m_pSteamScreenshots; } ISteamHTTP* SteamHTTP() const { return m_pSteamHTTP; } ISteamController* SteamController() const { return m_pController; } ISteamUGC* SteamUGC() const { return m_pSteamUGC; } ISteamAppList* SteamAppList() const { return m_pSteamAppList; } ISteamMusic* SteamMusic() const { return m_pSteamMusic; } ISteamMusicRemote* SteamMusicRemote() const { return m_pSteamMusicRemote; } ISteamHTMLSurface* SteamHTMLSurface() const { return m_pSteamHTMLSurface; } ISteamInventory* SteamInventory() const { return m_pSteamInventory; } ISteamVideo* SteamVideo() const { return m_pSteamVideo; } ISteamTV* SteamTV() const { return m_pSteamTV; } ISteamParentalSettings* SteamParentalSettings() const { return m_pSteamParentalSettings; } ISteamInput* SteamInput() const { return m_pSteamInput; } private: ISteamClient *m_pSteamClient; ISteamUser *m_pSteamUser; ISteamFriends *m_pSteamFriends; ISteamUtils *m_pSteamUtils; ISteamMatchmaking *m_pSteamMatchmaking; ISteamGameSearch *m_pSteamGameSearch; ISteamUserStats *m_pSteamUserStats; ISteamApps *m_pSteamApps; ISteamMatchmakingServers *m_pSteamMatchmakingServers; ISteamNetworking *m_pSteamNetworking; ISteamRemoteStorage *m_pSteamRemoteStorage; ISteamScreenshots *m_pSteamScreenshots; ISteamHTTP *m_pSteamHTTP; ISteamController *m_pController; ISteamUGC *m_pSteamUGC; ISteamAppList *m_pSteamAppList; ISteamMusic *m_pSteamMusic; ISteamMusicRemote *m_pSteamMusicRemote; ISteamHTMLSurface *m_pSteamHTMLSurface; ISteamInventory *m_pSteamInventory; ISteamVideo *m_pSteamVideo; ISteamTV *m_pSteamTV; ISteamParentalSettings *m_pSteamParentalSettings; ISteamInput *m_pSteamInput; }; class CSteamGameServerAPIContext { public: CSteamGameServerAPIContext() { Clear(); } inline void Clear() { memset( this, 0, sizeof(*this) ); } inline bool Init(); // NOTE: This is defined in steam_gameserver.h, to avoid this file having to include everything ISteamClient *SteamClient() const { return m_pSteamClient; } ISteamGameServer *SteamGameServer() const { return m_pSteamGameServer; } ISteamUtils *SteamGameServerUtils() const { return m_pSteamGameServerUtils; } ISteamNetworking *SteamGameServerNetworking() const { return m_pSteamGameServerNetworking; } ISteamGameServerStats *SteamGameServerStats() const { return m_pSteamGameServerStats; } ISteamHTTP *SteamHTTP() const { return m_pSteamHTTP; } ISteamInventory *SteamInventory() const { return m_pSteamInventory; } ISteamUGC *SteamUGC() const { return m_pSteamUGC; } ISteamApps *SteamApps() const { return m_pSteamApps; } private: ISteamClient *m_pSteamClient; ISteamGameServer *m_pSteamGameServer; ISteamUtils *m_pSteamGameServerUtils; ISteamNetworking *m_pSteamGameServerNetworking; ISteamGameServerStats *m_pSteamGameServerStats; ISteamHTTP *m_pSteamHTTP; ISteamInventory *m_pSteamInventory; ISteamUGC *m_pSteamUGC; ISteamApps *m_pSteamApps; };