X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg%2Fvg_steamworks.h;h=c0baba54bcca3dea04b42f4e9e0a411c913f4bdc;hb=7756287016b03ba7eb76b0a57cebe28952a4ce41;hp=d4b797bacfea4c9663fb6205954e47f39a7ad1ad;hpb=4e217c7bc7d079364a999ee39773fa70ca25733a;p=fishladder.git diff --git a/vg/vg_steamworks.h b/vg/vg_steamworks.h index d4b797b..c0baba5 100644 --- a/vg/vg_steamworks.h +++ b/vg/vg_steamworks.h @@ -301,6 +301,17 @@ typedef struct GameID_t #define SW_CBID_SteamAPICallCompleted (k_iSteamUtilsCallbacks + 3) +typedef enum ESteamAPICallFailure +{ + k_ESteamAPICallFailureNone = -1, // no failure + k_ESteamAPICallFailureSteamGone = 0, // the local Steam process has gone away + k_ESteamAPICallFailureNetworkFailure = 1, // the network connection to Steam has been broken, or was already broken + // SteamServersDisconnected_t callback will be sent around the same time + // SteamServersConnected_t will be sent when the client is able to talk to the Steam servers again + k_ESteamAPICallFailureInvalidHandle = 2, // the SteamAPICall_t handle passed in no longer exists + k_ESteamAPICallFailureMismatchedCallback = 3,// GetAPICallResult() was called with the wrong callback type for this API call +} ESteamAPICallFailure; + typedef u64 UGCHandle_t; typedef u64 PublishedFileUpdateHandle_t; typedef u64 PublishedFileId_t; @@ -534,6 +545,16 @@ void SteamAPI_ReleaseCurrentThreadMemory(); int SteamAPI_ISteamUserStats_SetAchievement( ISteamUserStats *self, const char *pchName ); +ESteamAPICallFailure SteamAPI_ISteamUtils_GetAPICallFailureReason( ISteamUtils* self, SteamAPICall_t hSteamAPICall ); + +// Friends +char *SteamAPI_ISteamFriends_GetPersonaName( ISteamFriends *self ); +const char *SteamAPI_ISteamFriends_GetFriendPersonaName( ISteamFriends *self, u64_steamid steamIDFriend ); +u64_steamid SteamAPI_ISteamUser_GetSteamID( ISteamUser *self ); +int SteamAPI_ISteamFriends_GetSmallFriendAvatar( ISteamFriends *self, u64_steamid steamIDFriend ); // 32x32 +int SteamAPI_ISteamUtils_GetImageSize( ISteamUtils *self, int iImage, u32 *pnWidth, u32 *pnHeight ); +int SteamAPI_ISteamUtils_GetImageRGBA( ISteamUtils *self, int iImage, u8 *pubDest, int nDestBufferSize ); + // Leaderboards SteamAPICall_t SteamAPI_ISteamUserStats_FindOrCreateLeaderboard( ISteamUserStats* self, const char * pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType ); SteamAPICall_t SteamAPI_ISteamUserStats_FindLeaderboard( ISteamUserStats* self, const char * pchLeaderboardName ); @@ -547,6 +568,18 @@ int SteamAPI_ISteamUserStats_GetDownloadedLeaderboardEntry( ISteamUserStats* sel SteamAPICall_t SteamAPI_ISteamUserStats_UploadLeaderboardScore( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, i32 nScore, const i32 * pScoreDetails, int cScoreDetailsCount ); SteamAPICall_t SteamAPI_ISteamUserStats_AttachLeaderboardUGC( ISteamUserStats* self, SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC ); +#define sw_get_image_size(...) SteamAPI_ISteamUtils_GetImageSize( steam_api_classes.utils, __VA_ARGS__ ) +#define sw_get_image_rgba(...) SteamAPI_ISteamUtils_GetImageRGBA( steam_api_classes.utils, __VA_ARGS__ ) +#define sw_get_small_friend_avatar(...) SteamAPI_ISteamFriends_GetSmallFriendAvatar( steam_api_classes.friends, __VA_ARGS__ ) +#define sw_get_steamid() SteamAPI_ISteamUser_GetSteamID( steam_api_classes.friends ) +#define sw_get_friend_persona_name(...) SteamAPI_ISteamFriends_GetFriendPersonaName( steam_api_classes.friends, __VA_ARGS__ ) +#define sw_get_persona_name() SteamAPI_ISteamFriends_GetPersonaName( steam_api_classes.friends ) +#define sw_find_leaderboard(...) SteamAPI_ISteamUserStats_FindLeaderboard( steam_api_classes.stats, __VA_ARGS__ ); +#define sw_get_leaderboard_name(...) SteamAPI_ISteamUserStats_GetLeaderboardName( steam_api_classes.stats, __VA_ARGS__ ) +#define sw_download_leaderboard_entries(...) SteamAPI_ISteamUserStats_DownloadLeaderboardEntries( steam_api_classes.stats, __VA_ARGS__ ) +#define sw_get_downloaded_entry(...) SteamAPI_ISteamUserStats_GetDownloadedLeaderboardEntry( steam_api_classes.stats, __VA_ARGS__ ) +#define sw_upload_leaderboard_score(...) SteamAPI_ISteamUserStats_UploadLeaderboardScore( steam_api_classes.stats, __VA_ARGS__ ) + HSteamPipe SteamAPI_GetHSteamPipe(); HSteamUser SteamAPI_GetHSteamUser(); @@ -556,20 +589,138 @@ struct ISteamUser *user; ISteamUserStats *stats; ISteamNetworking *net; + ISteamUtils *utils; HSteamPipe pipe; + + struct cached_player + { + u64_steamid id; + GLuint avatar_texture; // tex_unkown.name + + struct cached_player *l, *r; + } + cached_players[20]; + + struct cached_player *cache_head, *cache_tail; + + u32 cache_count; + } steam_api_classes; +static void _sw_cache_push( struct cached_player *player ) +{ + player->l = NULL; + player->r = steam_api_classes.cache_head; + if( steam_api_classes.cache_head ) steam_api_classes.cache_head->l = player; + if( !steam_api_classes.cache_tail ) steam_api_classes.cache_tail = player; + steam_api_classes.cache_head = player; + steam_api_classes.cache_count ++; +} + +static void _sw_cache_evict( struct cached_player *player ) +{ + if( player == steam_api_classes.cache_tail ) steam_api_classes.cache_tail = player->l; + if( player == steam_api_classes.cache_head ) steam_api_classes.cache_head = player->r; + if( player->l ) player->l->r = player->r; + if( player->r ) player->r->l = player->l; + steam_api_classes.cache_count --; +} + +static void _sw_access_cache( struct cached_player *player ) +{ + _sw_cache_evict( player ); + _sw_cache_push( player ); +} + +static GLuint sw_get_player_image( u64_steamid usr ) +{ + // Look for player in cache + for( int i = 0; i < steam_api_classes.cache_count; i ++ ) + { + struct cached_player *player = &steam_api_classes.cached_players[i]; + + if( player->id == usr ) + { + _sw_access_cache( player ); + return player->avatar_texture; + } + } + + struct cached_player *dest; + + if( steam_api_classes.cache_count == vg_list_size( steam_api_classes.cached_players ) ) + { + dest = steam_api_classes.cache_tail; + _sw_access_cache( dest ); + + // Delete previous before creating a new one + glDeleteTextures( 1, &dest->avatar_texture ); + } + else + { + dest = &steam_api_classes.cached_players[ steam_api_classes.cache_count ]; + _sw_cache_push( dest ); + } + + dest->id = usr; + dest->avatar_texture = 0; + + // Upload new image + u32 x = 32, y = 32; + int steam_image; + + steam_image = sw_get_small_friend_avatar( usr ); + if( !steam_image ) + return 0; + + if( !sw_get_image_size( steam_image, &x, &y ) ) + return 0; + + u8 * img_buf = (u8 *)malloc( x * y * 4 ); + + if( !sw_get_image_rgba(steam_image, img_buf, x * y * 4) ) + { + free( img_buf ); + return 0; + } + + glGenTextures( 1, &dest->avatar_texture ); + glBindTexture( GL_TEXTURE_2D, dest->avatar_texture ); + + 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 dest->avatar_texture; +} + ISteamFriends *SteamAPI_SteamFriends_v017(); ISteamUser *SteamAPI_SteamUser_v021(); ISteamUserStats *SteamAPI_SteamUserStats_v012(); ISteamNetworking *SteamAPI_SteamNetworking_v006(); +ISteamUtils *SteamAPI_SteamUtils_v010(); static void sw_exit(void) { SteamAPI_Shutdown(); } +// Needs to be manually called by client unfortunately +static void sw_free_opengl(void) +{ + for( int i = 0; i < steam_api_classes.cache_count; i ++ ) + if( steam_api_classes.cached_players[i].avatar_texture ) + glDeleteTextures( 1, &steam_api_classes.cached_players[i].avatar_texture ); +} + static int sw_init(void) { #if defined(VALVE_CALLBACK_PACK_SMALL) @@ -604,8 +755,9 @@ static int sw_init(void) steam_api_classes.user = SteamAPI_SteamUser_v021(); steam_api_classes.stats = SteamAPI_SteamUserStats_v012(); steam_api_classes.net = SteamAPI_SteamNetworking_v006(); + steam_api_classes.utils = SteamAPI_SteamUtils_v010(); - if( !steam_api_classes.friends || !steam_api_classes.user || !steam_api_classes.stats || !steam_api_classes.net ) + if( !steam_api_classes.friends || !steam_api_classes.user || !steam_api_classes.stats || !steam_api_classes.net || !steam_api_classes.utils ) { vg_error( "Steamworks interface pointers failed. Steamworks DLL may be old\n" ); SteamAPI_Shutdown(); @@ -619,6 +771,10 @@ static int sw_init(void) return 1; } + +void (*sw_leaderboard_found)( LeaderboardFindResult_t *pCallback ); +void (*sw_leaderboard_downloaded)( LeaderboardScoresDownloaded_t *pCallback ); + static void sw_event_loop(void) { SteamAPI_ManualDispatch_RunFrame( steam_api_classes.pipe ); @@ -626,10 +782,12 @@ static void sw_event_loop(void) while( SteamAPI_ManualDispatch_GetNextCallback( steam_api_classes.pipe, &callback ) ) { + vg_info( "steamworks_event::callback( %i )\n", callback.m_iCallback ); + // Check for dispatching API call results if( callback.m_iCallback == SW_CBID_SteamAPICallCompleted ){ - SteamAPICallCompleted_t *pCallCompleted = (SteamAPICallCompleted_t *)&callback; + SteamAPICallCompleted_t *pCallCompleted = (SteamAPICallCompleted_t *)callback.m_pubParam; void *pTmpCallResult = malloc( pCallCompleted->m_cubParam ); int bFailed; @@ -644,6 +802,37 @@ static void sw_event_loop(void) { // Dispatch the call result to the registered handler(s) for the // call identified by pCallCompleted->m_hAsyncCall + + vg_info( "steamworks_event::api_call_completed( %lu )\n", pCallCompleted->m_hAsyncCall ); + + switch( pCallCompleted->m_iCallback ) + { + case SW_CBID_LeaderboardFindResult: + if( sw_leaderboard_found ) sw_leaderboard_found( (LeaderboardFindResult_t*)pTmpCallResult ); + break; + case SW_CBID_LeaderboardScoresDownloaded: + if( sw_leaderboard_downloaded ) sw_leaderboard_downloaded( (LeaderboardScoresDownloaded_t*)pTmpCallResult ); + break; + default:break; + } + } + else + { + typedef enum ESteamAPICallFailure + { + k_ESteamAPICallFailureNone = -1, // no failure + k_ESteamAPICallFailureSteamGone = 0, // the local Steam process has gone away + k_ESteamAPICallFailureNetworkFailure = 1, // the network connection to Steam has been broken, or was already broken + // SteamServersDisconnected_t callback will be sent around the same time + // SteamServersConnected_t will be sent when the client is able to talk to the Steam servers again + k_ESteamAPICallFailureInvalidHandle = 2, // the SteamAPICall_t handle passed in no longer exists + k_ESteamAPICallFailureMismatchedCallback = 3,// GetAPICallResult() was called with the wrong callback type for this API call + } ESteamAPICallFailure; + + ESteamAPICallFailure fail_why = + SteamAPI_ISteamUtils_GetAPICallFailureReason( steam_api_classes.utils, pCallCompleted->m_hAsyncCall ); + + vg_error( "steamworks_event: error getting call result on %lu (code %d)\n", pCallCompleted->m_hAsyncCall, fail_why ); } free( pTmpCallResult ); @@ -652,9 +841,6 @@ static void sw_event_loop(void) { // 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 )