--- /dev/null
+/*
+ steamworks_thin.h - simple wrapper / macro set for building steamworks apps in pure C
+ Usage:
+ Put the latest steam_api.dll in your build folder
+ link against -lsteam_api
+
+ all functions are prefixed with sw_
+*/
+
+#ifndef STEAMWORKS_H
+#define STEAMWORKS_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+GLuint _localplayer_image;
+char _localplayer_name[128];
+
+#ifndef NO_STEAM
+
+#ifndef VOYAGER_RELEASE_MODE
+ #define STRUCTURE_PACK_CHECK
+#endif
+
+/*______________________________________________________________________________________________________________________________
+
+ ENUMS
+______________________________________________________________________________________________________________________________*/
+
+typedef enum{
+
+ k_ESteamIPTypeIPv4 = 0,
+ k_ESteamIPTypeIPv6 = 1,
+
+} ESteamIPType_t;
+
+typedef enum{
+
+ k_ESNetSocketConnectionTypeNotConnected = 0,
+ k_ESNetSocketConnectionTypeUDP = 1,
+ k_ESNetSocketConnectionTypeUDPRelay = 2,
+
+} ESNetSocketConnectionType_t;
+
+//-----------------------------------------------------------------------------
+// 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 };
+enum { k_iClientCompatCallbacks = 5800 };
+enum { k_iSteamChatCallbacks = 5900 };
+
+// Steam universes. Each universe is a self-contained Steam instance.
+typedef enum {
+ k_EUniverseInvalid = 0,
+ k_EUniversePublic = 1,
+ k_EUniverseBeta = 2,
+ k_EUniverseInternal = 3,
+ k_EUniverseDev = 4,
+ // k_EUniverseRC = 5, // no such universe anymore
+ k_EUniverseMax
+} EUniverse_t;
+
+typedef enum{
+ // Basic UDP send. Packets can't be bigger than 1200 bytes (your typical MTU size). Can be lost, or arrive out of order (rare).
+ // The sending API does have some knowledge of the underlying connection, so if there is no NAT-traversal accomplished or
+ // there is a recognized adjustment happening on the connection, the packet will be batched until the connection is open again.
+ k_EP2PSendUnreliable = 0,
+
+ // As above, but if the underlying p2p connection isn't yet established the packet will just be thrown away. Using this on the first
+ // packet sent to a remote host almost guarantees the packet will be dropped.
+ // This is only really useful for kinds of data that should never buffer up, i.e. voice payload packets
+ k_EP2PSendUnreliableNoDelay = 1,
+
+ // Reliable message send. Can send up to 1MB of data in a single message.
+ // Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for efficient sends of large chunks of data.
+ k_EP2PSendReliable = 2,
+
+ // As above, but applies the Nagle algorithm to the send - sends will accumulate
+ // until the current MTU size (typically ~1200 bytes, but can change) or ~200ms has passed (Nagle algorithm).
+ // Useful if you want to send a set of smaller messages but have the coalesced into a single packet
+ // Since the reliable stream is all ordered, you can do several small message sends with k_EP2PSendReliableWithBuffering and then
+ // do a normal k_EP2PSendReliable to force all the buffered data to be sent.
+ k_EP2PSendReliableWithBuffering = 3,
+
+} EP2PSend_t;
+
+// list of possible errors returned by SendP2PPacket() API
+// these will be posted in the P2PSessionConnectFail_t callback
+typedef enum {
+ k_EP2PSessionErrorNone = 0,
+ k_EP2PSessionErrorNotRunningApp = 1, // target is not running the same game
+ k_EP2PSessionErrorNoRightsToApp = 2, // local user doesn't own the app that is running
+ k_EP2PSessionErrorDestinationNotLoggedIn = 3, // target user isn't connected to Steam
+ k_EP2PSessionErrorTimeout = 4, // target isn't responding, perhaps not calling AcceptP2PSessionWithUser()
+ // corporate firewalls can also block this (NAT traversal is not firewall traversal)
+ // make sure that UDP ports 3478, 4379, and 4380 are open in an outbound direction
+ k_EP2PSessionErrorMax = 5
+} EP2PSessionError_t;
+
+typedef enum {
+
+ k_EFriendFlagNone = 0x00,
+ k_EFriendFlagBlocked = 0x01,
+ k_EFriendFlagFriendshipRequested = 0x02,
+ k_EFriendFlagImmediate = 0x04, // "regular" friend
+ k_EFriendFlagClanMember = 0x08,
+ k_EFriendFlagOnGameServer = 0x10,
+ // k_EFriendFlagHasPlayedWith = 0x20, // not currently used
+ // k_EFriendFlagFriendOfFriend = 0x40, // not currently used
+ k_EFriendFlagRequestingFriendship = 0x80,
+ k_EFriendFlagRequestingInfo = 0x100,
+ k_EFriendFlagIgnored = 0x200,
+ k_EFriendFlagIgnoredFriend = 0x400,
+ // k_EFriendFlagSuggested = 0x800, // not used
+ k_EFriendFlagChatMember = 0x1000,
+ k_EFriendFlagAll = 0xFFFF,
+
+} EFriendFlags_t;
+
+// size limits on Rich Presence data
+enum { k_cchMaxRichPresenceKeys = 30 };
+enum { k_cchMaxRichPresenceKeyLength = 64 };
+enum { k_cchMaxRichPresenceValueLength = 256 };
+
+/*______________________________________________________________________________________________________________________________
+
+ STEAM TYPES
+______________________________________________________________________________________________________________________________*/
+
+// Redefube class pointers to void
+typedef void ISteamFriends;
+typedef void ISteamUserStats;
+typedef void ISteamUtils;
+typedef void ISteamUser;
+typedef void ISteamNetworking;
+
+typedef int32_t HSteamPipe;
+typedef int32_t HSteamUser;
+
+typedef int E_iCallBack_t;
+
+typedef uint32_t SNetSocket_t; // CreateP2PConnectionSocket()
+typedef uint32_t SNetListenSocket_t; // CreateListenSocket()
+
+typedef uint64_t uint64_steamid;
+typedef uint64_t SteamAPICall_t;
+
+/*______________________________________________________________________________________________________________________________
+
+ PACKING: 1 Byte
+______________________________________________________________________________________________________________________________*/
+
+#pragma pack( push, 1 )
+
+typedef struct
+{
+ // 64 bits total
+ union {
+ struct SteamIDComponent_t
+ {
+#ifdef VALVE_BIG_ENDIAN
+ EUniverse_t m_EUniverse : 8; // universe this account belongs to
+ unsigned int m_EAccountType : 4; // type of account - can't show as EAccountType, due to signed / unsigned difference
+ unsigned int m_unAccountInstance : 20; // dynamic instance ID
+ uint32_t m_unAccountID : 32; // unique account identifier
+#else
+ uint32_t m_unAccountID : 32; // unique account identifier
+ unsigned int m_unAccountInstance : 20; // dynamic instance ID
+ unsigned int m_EAccountType : 4; // type of account - can't show as EAccountType, due to signed / unsigned difference
+ EUniverse_t m_EUniverse : 8; // universe this account belongs to
+#endif
+ } m_comp;
+
+ uint64_t m_unAll64Bits;
+ };
+} CSteamID;
+
+typedef struct{
+ union {
+
+ uint32_t m_unIPv4; // Host order
+ uint8_t m_rgubIPv6[16]; // Network order! Same as inaddr_in6. (0011:2233:4455:6677:8899:aabb:ccdd:eeff)
+
+ // Internal use only
+ uint64_t m_ipv6Qword[2]; // big endian
+
+ };
+
+ ESteamIPType_t m_eType;
+
+} SteamIPAddress_t;
+
+#pragma pack(pop)
+
+/*______________________________________________________________________________________________________________________________
+
+ PACKING: Some kind of strange alignment thing
+______________________________________________________________________________________________________________________________*/
+
+#if defined(__linux__) || defined(__APPLE__)
+// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+// The 64-bit version of gcc has the alignment requirement for these types set to
+// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+ #define VALVE_CALLBACK_PACK_SMALL
+#else
+ #define VALVE_CALLBACK_PACK_LARGE
+#endif
+
+#if defined( VALVE_CALLBACK_PACK_SMALL )
+ #pragma pack( push, 4 )
+#elif defined( VALVE_CALLBACK_PACK_LARGE )
+ #pragma pack( push, 8 )
+#else
+ #error steam_api_common.h should define VALVE_CALLBACK_PACK_xxx
+#endif
+
+typedef struct{
+
+ uint8_t m_bConnectionActive; // true if we've got an active open connection
+ uint8_t m_bConnecting; // true if we're currently trying to establish a connection
+ uint8_t m_eP2PSessionError; // last error recorded (see enum above)
+ uint8_t m_bUsingRelay; // true if it's going through a relay server (TURN)
+ int32_t m_nBytesQueuedForSend;
+ int32_t m_nPacketsQueuedForSend;
+ uint32_t m_nRemoteIP; // potential IP:Port of remote host. Could be TURN server.
+ uint16_t m_nRemotePort; // Only exists for compatibility with older authentication api's
+
+} P2PSessionState_t;
+
+typedef struct {
+
+ HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
+ int m_iCallback; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.)
+ uint8_t *m_pubParam; // Points to the callback structure
+ int m_cubParam; // Size of the data pointed to by m_pubParam
+
+} CallbackMsg_t;
+
+typedef struct {
+
+ SteamAPICall_t m_hAsyncCall;
+ int m_iCallback;
+ uint32_t m_cubParam;
+
+} SteamAPICallCompleted_t;
+#define SW_CBID_SteamAPICallCompleted (k_iSteamUtilsCallbacks + 3)
+
+
+// callback notification - a user wants to talk to us over the P2P channel via the SendP2PPacket() API
+// in response, a call to AcceptP2PPacketsFromUser() needs to be made, if you want to talk with them
+typedef struct {
+
+ CSteamID m_steamIDRemote; // user who wants to talk to us
+
+} P2PSessionRequest_t;
+#define SW_CBID_P2PSessionRequest (k_iSteamNetworkingCallbacks + 2)
+
+
+// callback notification - packets can't get through to the specified user via the SendP2PPacket() API
+// all packets queued packets unsent at this point will be dropped
+// further attempts to send will retry making the connection (but will be dropped if we fail again)
+typedef struct {
+
+ CSteamID m_steamIDRemote; // user we were sending packets to
+ uint8_t m_eP2PSessionError; // EP2PSessionError indicating why we're having trouble
+
+} P2PSessionConnectFail_t;
+#define SW_CBID_P2PSessionConnectFail (k_iSteamNetworkingCallbacks + 3)
+
+// callback notification - status of a socket has changed
+// used as part of the CreateListenSocket() / CreateP2PConnectionSocket()
+typedef struct {
+
+ SNetSocket_t m_hSocket; // the socket used to send/receive data to the remote host
+ SNetListenSocket_t m_hListenSocket; // this is the server socket that we were listening on; NULL if this was an outgoing connection
+ CSteamID m_steamIDRemote; // remote steamID we have connected to, if it has one
+ int m_eSNetSocketState; // socket state, ESNetSocketState
+
+} SocketStatusCallback_t;
+#define SW_CBID_SocketStatusCallback (k_iSteamNetworkingCallbacks + 1)
+
+//-----------------------------------------------------------------------------
+// Purpose: called when the user tries to join a game from their friends list
+// rich presence will have been set with the "connect" key which is set here
+//-----------------------------------------------------------------------------
+typedef struct {
+ CSteamID m_steamIDFriend; // the friend they did the join via (will be invalid if not directly via a friend)
+ char m_rgchConnect[k_cchMaxRichPresenceValueLength];
+} GameRichPresenceJoinRequested_t;
+#define SW_CBID_GameRichPresenceJoinRequested (k_iSteamFriendsCallbacks + 37)
+
+// Making SURE we have alignment
+#ifdef STRUCTURE_PACK_CHECK
+typedef struct {
+ uint32_t m_u32;
+ uint64_t m_u64;
+ uint16_t m_u16;
+ double m_d;
+} ValvePackingSentinel_t;
+#endif
+
+#pragma pack( pop )
+
+#ifndef NO_STEAM
+
+/*______________________________________________________________________________________________________________________________
+
+ Forward linker declerations. Type: cdecl (obviously)
+______________________________________________________________________________________________________________________________*/
+
+void SteamAPI_Shutdown();
+int SteamAPI_Init();
+int SteamAPI_RestartAppIfNecessary( uint32_t unOwnAppID );
+
+void SteamAPI_ManualDispatch_Init();
+void SteamAPI_ManualDispatch_RunFrame( HSteamPipe hSteamPipe );
+int SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe hSteamPipe, CallbackMsg_t *pCallbackMsg );
+void SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe hSteamPipe );
+int SteamAPI_ManualDispatch_GetAPICallResult( HSteamPipe hSteamPipe, SteamAPICall_t hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, int *pbFailed );
+
+
+char *SteamAPI_ISteamFriends_GetPersonaName( ISteamFriends *self );
+const char *SteamAPI_ISteamFriends_GetFriendPersonaName( ISteamFriends *self, uint64_steamid steamIDFriend );
+uint64_steamid SteamAPI_ISteamUser_GetSteamID( ISteamUser *self );
+int SteamAPI_ISteamFriends_SetRichPresence( ISteamFriends* self, const char * pchKey, const char * pchValue );
+int SteamAPI_ISteamFriends_HasFriend( ISteamFriends* self, uint64_steamid steamIDFriend, int iFriendFlags );
+int SteamAPI_ISteamFriends_GetSmallFriendAvatar ( ISteamFriends *self, uint64_steamid steamIDFriend ); // 32x32
+int SteamAPI_ISteamFriends_GetMediumFriendAvatar ( ISteamFriends *self, uint64_steamid steamIDFriend );
+int SteamAPI_ISteamFriends_GetLargeFriendAvatar ( ISteamFriends *self, uint64_steamid steamIDFriend );
+int SteamAPI_ISteamUtils_GetImageSize( ISteamUtils *self, int iImage, uint32_t *pnWidth, uint32_t *pnHeight );
+int SteamAPI_ISteamUtils_GetImageRGBA( ISteamUtils *self, int iImage, uint8_t *pubDest, int nDestBufferSize );
+int SteamAPI_ISteamUserStats_SetAchievement( ISteamUserStats *self, const char *pchName );
+
+HSteamPipe SteamAPI_GetHSteamPipe();
+HSteamUser SteamAPI_GetHSteamUser();
+
+/* NETWORKING INTERFACES
+-------------------------*/
+
+int /* SendP2PPacket */ SteamAPI_ISteamNetworking_SendP2PPacket( ISteamNetworking *self,
+ uint64_steamid steamIDRemote,
+ const void *pubData,
+ uint32_t cubData,
+ EP2PSend_t eP2PSendType,
+ int nChannel
+);
+
+int /* IsP2PPacketAvailable */ SteamAPI_ISteamNetworking_IsP2PPacketAvailable( ISteamNetworking *self,
+ uint32_t *pcubMsgSize,
+ int nChannel
+);
+
+int /* ReadP2PPacket */ SteamAPI_ISteamNetworking_ReadP2PPacket( ISteamNetworking *self,
+ void *pubDest,
+ uint32_t cubDest,
+ uint32_t *pcubMsgSize,
+ CSteamID *psteamIDRemote,
+ int nChannel
+);
+
+int /* AcceptP2PSessionWithUser */ SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser( ISteamNetworking *self,
+ uint64_steamid steamIDRemote
+);
+
+int /* CloseP2PSessionWithUser */ SteamAPI_ISteamNetworking_CloseP2PSessionWithUser( ISteamNetworking *self,
+ uint64_steamid steamIDRemote
+);
+
+int /* CloseP2PChannelWithUser */ SteamAPI_ISteamNetworking_CloseP2PChannelWithUser( ISteamNetworking *self,
+ uint64_steamid steamIDRemote,
+ int nChannel
+);
+
+int /* GetP2PSessionState */ SteamAPI_ISteamNetworking_GetP2PSessionState( ISteamNetworking *self,
+ uint64_steamid steamIDRemote,
+ P2PSessionState_t *pConnectionState
+);
+
+int /* AllowP2PPacketRelay */ SteamAPI_ISteamNetworking_AllowP2PPacketRelay( ISteamNetworking *self,
+ int bAllow
+);
+
+SNetListenSocket_t /* CreateListenSocket */ SteamAPI_ISteamNetworking_CreateListenSocket( ISteamNetworking *self,
+ int nVirtualP2PPort,
+ SteamIPAddress_t nIP,
+ uint16_t nPort,
+ int bAllowUseOfPacketRelay
+);
+
+SNetSocket_t /* CreateP2PConnectionSocket */ SteamAPI_ISteamNetworking_CreateP2PConnectionSocket( ISteamNetworking *self,
+ uint64_steamid steamIDTarget,
+ int nVirtualPort,
+ int nTimeoutSec,
+ int bAllowUseOfPacketRelay
+);
+
+SNetSocket_t /* CreateConnectionSocket */ SteamAPI_ISteamNetworking_CreateConnectionSocket( ISteamNetworking *self,
+ SteamIPAddress_t nIP,
+ uint16_t nPort,
+ int nTimeoutSec
+);
+
+int /* DestroySocket */ SteamAPI_ISteamNetworking_DestroySocket( ISteamNetworking *self,
+ SNetSocket_t hSocket,
+ int bNotifyRemoteEnd
+);
+
+int /* DestroyListenSocket */ SteamAPI_ISteamNetworking_DestroyListenSocket( ISteamNetworking *self,
+ SNetListenSocket_t hSocket,
+ int bNotifyRemoteEnd
+);
+
+int /* SendDataOnSocket */ SteamAPI_ISteamNetworking_SendDataOnSocket( ISteamNetworking *self,
+ SNetSocket_t hSocket,
+ void *pubData,
+ uint32_t cubData,
+ int bReliable
+);
+
+int /* IsDataAvailableOnSocket */ SteamAPI_ISteamNetworking_IsDataAvailableOnSocket( ISteamNetworking *self,
+ SNetSocket_t hSocket,
+ uint32_t *pcubMsgSize
+);
+
+int /* RetrieveDataFromSocket */ SteamAPI_ISteamNetworking_RetrieveDataFromSocket( ISteamNetworking *self,
+ SNetSocket_t hSocket,
+ void *pubDest,
+ uint32_t cubDest,
+ uint32_t *pcubMsgSize
+);
+
+int /* IsDataAvailable */ SteamAPI_ISteamNetworking_IsDataAvailable( ISteamNetworking *self,
+ SNetListenSocket_t hListenSocket,
+ uint32_t *pcubMsgSize,
+ SNetSocket_t *phSocket
+);
+
+int /* RetrieveData */ SteamAPI_ISteamNetworking_RetrieveData( ISteamNetworking *self,
+ SNetListenSocket_t hListenSocket,
+ void *pubDest,
+ uint32_t cubDest,
+ uint32_t *pcubMsgSize,
+ SNetSocket_t *phSocket
+);
+
+int /* GetSocketInfo */ SteamAPI_ISteamNetworking_GetSocketInfo( ISteamNetworking *self,
+ SNetSocket_t hSocket,
+ CSteamID *pSteamIDRemote,
+ int *peSocketStatus,
+ SteamIPAddress_t *punIPRemote,
+ uint16_t *punPortRemote
+);
+
+int /* GetListenSocketInfo */ SteamAPI_ISteamNetworking_GetListenSocketInfo( ISteamNetworking *self,
+ SNetListenSocket_t hListenSocket,
+ SteamIPAddress_t *pnIP,
+ uint16_t *pnPort
+);
+
+ESNetSocketConnectionType_t /* GetSocketConnectionType */ SteamAPI_ISteamNetworking_GetSocketConnectionType( ISteamNetworking *self,
+ SNetSocket_t hSocket
+);
+
+int /* GetMaxPacketSize */ SteamAPI_ISteamNetworking_GetMaxPacketSize( ISteamNetworking *self,
+ SNetSocket_t hSocket
+);
+
+#define sw_SteamAPI_Shutdown SteamAPI_Shutdown
+#define sw_SteamAPI_Init() SteamAPI_Init()
+#define sw_SteamAPI_RestartAppIfNecessary(...) SteamAPI_RestartAppIfNecessary( __VA_ARGS__ )
+
+// This method can only be cleared correctly in first party c++ mode
+// See: sw_SteamAPI_ManualDispatch_Init
+// #define sw_SteamAPI_RunCallbacks()
+
+// Steam pipe stuff
+#define sw_SteamAPI_GetHSteamPipe() SteamAPI_GetHSteamPipe()
+#define sw_SteamAPI_GetHSteamUser() SteamAPI_GetHSteamUser()
+
+#define sw_SteamAPI_ManualDispatch_Init() SteamAPI_ManualDispatch_Init()
+#define sw_SteamAPI_ManualDispatch_GetNextCallback(...) SteamAPI_ManualDispatch_GetNextCallback( __VA_ARGS__ )
+#define sw_SteamAPI_ManualDispatch_FreeLastCallback(...) SteamAPI_ManualDispatch_FreeLastCallback( __VA_ARGS__ )
+#define sw_SteamAPI_ManualDispatch_GetAPICallResult(...) SteamAPI_ManualDispatch_GetAPICallResult( __VA_ARGS__ )
+#define sw_SteamAPI_ManualDispatch_RunFrame(...) SteamAPI_ManualDispatch_RunFrame( __VA_ARGS__ )
+
+#define sw_GetPersonaName(...) SteamAPI_ISteamFriends_GetPersonaName( __thinsteam_friends, ##__VA_ARGS__ )
+#define sw_GetFriendPersonaName(...) SteamAPI_ISteamFriends_GetFriendPersonaName( __thinsteam_friends, __VA_ARGS__ )
+#define sw_GetSteamID(...) SteamAPI_ISteamUser_GetSteamID( __thinsteam_user, ##__VA_ARGS__ )
+#define sw_HasFriend(...) SteamAPI_ISteamFriends_HasFriend( __thinsteam_friends, __VA_ARGS__ )
+#define sw_SetRichPresence(...) SteamAPI_ISteamFriends_SetRichPresence( __thinsteam_friends, __VA_ARGS__ )
+
+#define sw_GetSmallFriendAvatar(...) SteamAPI_ISteamFriends_GetSmallFriendAvatar( __thinsteam_friends, ##__VA_ARGS__ )
+#define sw_GetMediumFriendAvatar(...) SteamAPI_ISteamFriends_GetMediumFriendAvatar( __thinsteam_friends, ##__VA_ARGS__ )
+#define sw_GetLargeFriendAvatar(...) SteamAPI_ISteamFriends_GetLargeFriendAvatar( __thinsteam_friends, ##__VA_ARGS__ )
+#define sw_GetImageSize(...) SteamAPI_ISteamUtils_GetImageSize( __thinsteam_utils, ##__VA_ARGS__ )
+#define sw_GetImageRGBA(...) SteamAPI_ISteamUtils_GetImageRGBA( __thinsteam_utils, ##__VA_ARGS__ )
+
+#define sw_SetAchievement(...) SteamAPI_ISteamUserStats_SetAchievement( __thinsteam_stats, ##__VA_ARGS__ )
+
+// https://partner.steamgames.com/doc/api/ISteamNetworkingUtils
+#define sw_SendP2PPacket(...) SteamAPI_ISteamNetworking_SendP2PPacket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_IsP2PPacketAvailable(...) SteamAPI_ISteamNetworking_IsP2PPacketAvailable( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_ReadP2PPacket(...) SteamAPI_ISteamNetworking_ReadP2PPacket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_AcceptP2PSessionWithUser(...) SteamAPI_ISteamNetworking_AcceptP2PSessionWithUser( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_CloseP2PSessionWithUser(...) SteamAPI_ISteamNetworking_CloseP2PSessionWithUser( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_CloseP2PChannelWithUser(...) SteamAPI_ISteamNetworking_CloseP2PChannelWithUser( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_GetP2PSessionState(...) SteamAPI_ISteamNetworking_GetP2PSessionState( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_AllowP2PPacketRelay(...) SteamAPI_ISteamNetworking_AllowP2PPacketRelay( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_CreateListenSocket(...) SteamAPI_ISteamNetworking_CreateListenSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_CreateP2PConnectionSocket(...) SteamAPI_ISteamNetworking_CreateP2PConnectionSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_CreateConnectionSocket(...) SteamAPI_ISteamNetworking_CreateConnectionSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_DestroySocket(...) SteamAPI_ISteamNetworking_DestroySocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_DestroyListenSocket(...) SteamAPI_ISteamNetworking_DestroyListenSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_SendDataOnSocket(...) SteamAPI_ISteamNetworking_SendDataOnSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_IsDataAvailableOnSocket(...) SteamAPI_ISteamNetworking_IsDataAvailableOnSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_RetrieveDataFromSocket(...) SteamAPI_ISteamNetworking_RetrieveDataFromSocket( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_IsDataAvailable(...) SteamAPI_ISteamNetworking_IsDataAvailable( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_RetrieveData(...) SteamAPI_ISteamNetworking_RetrieveData( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_GetSocketInfo(...) SteamAPI_ISteamNetworking_GetSocketInfo( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_GetListenSocketInfo(...) SteamAPI_ISteamNetworking_GetListenSocketInfo( __thinsteam_net, ##__VA_ARGS__ )
+#define sw_GetSocketConnectionType(...) SteamAPI_ISteamNetworking_GetSocketConnectionType( __thinsteam_net,##__VA_ARGS__ )
+#define sw_GetMaxPacketSize(...) SteamAPI_ISteamNetworking_GetMaxPacketSize( __thinsteam_net, ##__VA_ARGS__ )
+
+#define _sw__fill( self, func, ... ) func( self, ##__VA_ARGS__ )
+#endif
+
+/*______________________________________________________________________________________________________________________________
+
+ WRAPPER LAYER
+______________________________________________________________________________________________________________________________*/
+
+ISteamFriends *__thinsteam_friends = NULL;
+ISteamUser *__thinsteam_user = NULL;
+ISteamUtils *__thinsteam_utils = NULL;
+ISteamUserStats *__thinsteam_stats = NULL;
+ISteamNetworking *__thinsteam_net = NULL;
+
+ISteamFriends *SteamAPI_SteamFriends_v017();
+ISteamUser *SteamAPI_SteamUser_v021();
+ISteamUtils *SteamAPI_SteamUtils_v009();
+ISteamUserStats *SteamAPI_SteamUserStats_v012();
+ISteamNetworking *SteamAPI_SteamNetworking_v006();
+
+HSteamPipe g_hSteamPipe;
+
+GLuint get_player_image( uint64_steamid usr )
+{
+ GLuint gl_img;
+
+ uint32_t x = 64, y = 64;
+ int steam_image;
+
+ steam_image = sw_GetMediumFriendAvatar( usr );
+ sw_GetImageSize( steam_image, &x, &y );
+
+ unsigned char * img_buf = (unsigned char *)calloc( x * y * 4, 1 );
+
+ sw_GetImageRGBA( steam_image, img_buf, x * y * 4 );
+
+ glGenTextures( 1, &gl_img );
+ glBindTexture( GL_TEXTURE_2D, gl_img );
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_buf );
+ glGenerateMipmap( GL_TEXTURE_2D );
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ free( img_buf );
+
+ return gl_img;
+}
+
+int sw_vipid( uint64_steamid usr )
+{
+ static uint64_steamid massiveLEGENDS[] =
+ {
+ 76561198134179460, // Spud
+ 76561198020563704, // Assasssin
+ 76561198062961277, // lopen
+ 76561198084693332 // ernie
+ };
+
+ for( int i = 0; i < sizeof(massiveLEGENDS)/sizeof(massiveLEGENDS[0]); i ++ )
+ {
+ if( massiveLEGENDS[i] == usr )
+ return 1;
+ }
+
+ return 0;
+}
+
+// Initialize steamworks through this function and your appid
+int sw_init( uint32_t appid ) {
+
+#ifdef STRUCTURE_PACK_CHECK
+
+// This code should never fail and if it does something went wrong with the build
+// Remember to undefine STRUCTURE_PACK_CHECK for publishing!!!
+
+#if defined(VALVE_CALLBACK_PACK_SMALL)
+ if( sizeof(ValvePackingSentinel_t) != 24 ){
+ printf( "Struct packing error: ValvePackingSentinel_t expected 24 got %i\nThe application is built incorrectly\n", (int)sizeof(ValvePackingSentinel_t));
+ return 0;
+ }
+#elif defined(VALVE_CALLBACK_PACK_LARGE)
+ if( sizeof(ValvePackingSentinel_t) != 32 ){
+ printf( "Struct packing error: ValvePackingSentinel_t expected 32 got %i\nThe application is built incorrectly\n", (int)sizeof(ValvePackingSentinel_t));
+ return 0;
+ }
+#else
+ #error ???
+#endif
+
+#endif
+
+ #ifdef STEAMWORKS_VERBOSE
+ printf( "Initializing steamworks..\n" );
+ #endif
+
+ if( sw_SteamAPI_RestartAppIfNecessary( appid ) == 1 ){
+ #ifdef STEAMWORKS_VERBOSE
+ printf( "Restarting via steam\n" );
+ #endif
+ return 0;
+ }
+
+ if( !sw_SteamAPI_Init() ){
+ #ifdef STEAMWORKS_VERBOSE
+ printf( "Steamworks connection failed\n" );
+ #endif
+ return 0;
+ }
+
+ // We are using C so we have to deal with callbacks microsoft event loop style
+ sw_SteamAPI_ManualDispatch_Init();
+
+ __thinsteam_friends = SteamAPI_SteamFriends_v017();
+ __thinsteam_user = SteamAPI_SteamUser_v021();
+ __thinsteam_utils = SteamAPI_SteamUtils_v009();
+ __thinsteam_stats = SteamAPI_SteamUserStats_v012();
+ __thinsteam_net = SteamAPI_SteamNetworking_v006();
+
+ // This might happen if the DLL is too old
+ if( !__thinsteam_friends | !__thinsteam_user | !__thinsteam_utils | !__thinsteam_stats | !__thinsteam_net ){
+ #ifdef STEAMWORKS_VERBOSE
+ printf( "Interface hooks failed\n" );
+ #endif
+ return 0;
+ }
+
+ g_hSteamPipe = sw_SteamAPI_GetHSteamPipe();
+
+ #ifdef STEAMWORKS_VERBOSE
+ printf( "Steamworks ready\n" );
+ #endif
+
+ return 1;
+}
+
+void sw_init_postgl()
+{
+ _localplayer_image = get_player_image( sw_GetSteamID() );
+ strcpy( _localplayer_name, sw_GetPersonaName() );
+}
+
+/*______________________________________________________________________________________________________________________________
+
+ USER CODE
+______________________________________________________________________________________________________________________________*/
+
+// Macro Creates <name>(args):
+// Function(args) pointer definition
+// <name> Callback global pointer
+// sw_Set<name>Callback (*ptr) function
+
+#define _swCallbackPair( CNAME, ... ) \
+typedef void(*sw_##CNAME##Fun)( __VA_ARGS__ ); \
+sw_##CNAME##Fun CNAME = NULL; \
+void sw_Set##CNAME##Callback(sw_##CNAME##Fun d) { CNAME = d; }
+
+_swCallbackPair( OnSocketStatus, SNetSocket_t, SNetListenSocket_t, CSteamID, int )
+_swCallbackPair( OnP2PSessionConnectFail, CSteamID, EP2PSessionError_t )
+_swCallbackPair( OnP2PSessionRequest, CSteamID )
+_swCallbackPair( OnSteamJoinRequest, CSteamID, char * )
+
+void sw_RunSteamEventLoop(void)
+{
+ sw_SteamAPI_ManualDispatch_RunFrame( g_hSteamPipe );
+ CallbackMsg_t callback;
+ while( sw_SteamAPI_ManualDispatch_GetNextCallback( g_hSteamPipe, &callback ) ){
+
+ // Check for dispatching API call results
+ if( callback.m_iCallback == SW_CBID_SteamAPICallCompleted ){
+
+ SteamAPICallCompleted_t *pCallCompleted = (SteamAPICallCompleted_t *)&callback;
+ void *pTmpCallResult = malloc( pCallCompleted->m_cubParam );
+ int bFailed;
+
+ if( sw_SteamAPI_ManualDispatch_GetAPICallResult( g_hSteamPipe, pCallCompleted->m_hAsyncCall, pTmpCallResult, \
+ pCallCompleted->m_cubParam, pCallCompleted->m_iCallback, &bFailed ) ){
+
+ // Dispatch the call result to the registered handler(s) for the
+ // call identified by pCallCompleted->m_hAsyncCall
+
+ }
+
+ free( pTmpCallResult );
+
+ } else {
+
+ // Look at callback.m_iCallback to see what kind of callback it is,
+ // and dispatch to appropriate handler(s)
+
+ vg_info( "steamworks_event::callback( %i )\n", callback.m_iCallback );
+
+ void *data = callback.m_pubParam;
+
+ switch( callback.m_iCallback ){
+
+ case SW_CBID_P2PSessionRequest: if( OnP2PSessionRequest ) OnP2PSessionRequest(
+ ((P2PSessionRequest_t *)data)->m_steamIDRemote
+ ); break;
+
+ case SW_CBID_SocketStatusCallback: if( OnSocketStatus ) OnSocketStatus(
+ ((SocketStatusCallback_t *)data)->m_hSocket,
+ ((SocketStatusCallback_t *)data)->m_hListenSocket,
+ ((SocketStatusCallback_t *)data)->m_steamIDRemote,
+ ((SocketStatusCallback_t *)data)->m_eSNetSocketState
+ ); break;
+
+ case SW_CBID_P2PSessionConnectFail: if( OnP2PSessionConnectFail ) OnP2PSessionConnectFail(
+ ((P2PSessionConnectFail_t *)data)->m_steamIDRemote,
+ ((P2PSessionConnectFail_t *)data)->m_eP2PSessionError
+ ); break;
+
+ case SW_CBID_GameRichPresenceJoinRequested: if( OnSteamJoinRequest ) OnSteamJoinRequest(
+ ((GameRichPresenceJoinRequested_t *)data)->m_steamIDFriend,
+ ((GameRichPresenceJoinRequested_t *)data)->m_rgchConnect
+ ); break;
+
+ default: break;
+
+ }
+
+ }
+
+ SteamAPI_ManualDispatch_FreeLastCallback( g_hSteamPipe );
+
+ }
+
+}
+
+/*______________________________________________________________________________________________________________________________
+
+ NO_STEAM
+______________________________________________________________________________________________________________________________*/
+
+#else // #define NO_STEAM
+// In case we dont want to spam the steam servers
+
+char *__str_sw_unlinked = "__NO_STEAMWORKS__";
+
+#define SW_BLANK_RETURN 0
+
+#define sw_init( x ) 1
+#define sw_exit()
+#define sw_runcallbacks()
+#define sw_get_persona_name() __str_sw_unlinked
+#define sw_get_steamid() SW_BLANK_RETURN
+#define sw_get_friend_smallavatar( x ) SW_BLANK_RETURN
+#define sw_get_friend_mediumavatar( x ) SW_BLANK_RETURN
+#define sw_get_friend_largeavatar( x ) SW_BLANK_RETURN
+
+#define sw_get_image_size( x, y, z )
+#define sw_get_image_rgba( x, y, z )
+#define sw_set_achievement( x )
+
+#endif
+
+#endif
+