From 58083e0863c129994bfc0f4a18e1c07bd5f114d5 Mon Sep 17 00:00:00 2001 From: Mr_Goldberg Date: Sat, 7 Sep 2019 09:39:41 -0400 Subject: [PATCH] Started work on a real avatars implementation. Fix issue where since the image ids changed for every get avatar call mudrunner would keep allocating memory indefinitely. --- dll/settings.cpp | 13 +++++++++- dll/settings.h | 10 ++++++++ dll/steam_friends.h | 61 ++++++++++++++++++++++++++++++++++----------- dll/steam_utils.h | 26 ++++++++----------- 4 files changed, 80 insertions(+), 30 deletions(-) diff --git a/dll/settings.cpp b/dll/settings.cpp index 46771a48..95ab05a9 100644 --- a/dll/settings.cpp +++ b/dll/settings.cpp @@ -202,4 +202,15 @@ void Settings::setLeaderboard(std::string leaderboard, enum ELeaderboardSortMeth leader.display_type = display_type; leaderboards[leaderboard] = leader; -} \ No newline at end of file +} + +int Settings::add_image(std::string data, uint32 width, uint32 height) +{ + int last = images.size() + 1; + struct Image_Data dt; + dt.width = width; + dt.height = height; + dt.data = data; + images[last] = dt; + return last; +} diff --git a/dll/settings.h b/dll/settings.h index cd6d1de8..d787abbd 100644 --- a/dll/settings.h +++ b/dll/settings.h @@ -52,6 +52,12 @@ struct Stat_config { }; }; +struct Image_Data { + uint32 width; + uint32 height; + std::string data; +}; + class Settings { CSteamID steam_id; CGameID game_id; @@ -116,6 +122,10 @@ public: //stats std::map getStats() { return stats; } void setStatDefiniton(std::string name, struct Stat_config stat_config) {stats[name] = stat_config; } + + //images + std::map images; + int add_image(std::string data, uint32 width, uint32 height); }; #endif diff --git a/dll/steam_friends.h b/dll/steam_friends.h index 145a1d5a..9453c89f 100644 --- a/dll/steam_friends.h +++ b/dll/steam_friends.h @@ -19,6 +19,12 @@ #define SEND_FRIEND_RATE 4.0 +struct Avatar_Numbers { + int smallest; + int medium; + int large; +}; + class Steam_Friends : public ISteamFriends004, public ISteamFriends005, @@ -45,7 +51,7 @@ public ISteamFriends bool modified; std::vector friends; - unsigned img_count; + std::map avatars; CSteamID lobby_id; std::chrono::high_resolution_clock::time_point last_sent_friends; @@ -82,6 +88,29 @@ bool isAppIdCompatible(Friend *f) return settings->get_local_game_id().AppID() == f->appid(); } +struct Avatar_Numbers add_friend_avatars(CSteamID id) +{ + uint64 steam_id = id.ConvertToUint64(); + auto avatar_ids = avatars.find(steam_id); + if (avatar_ids != avatars.end()) { + return avatar_ids->second; + } + + //TODO: get real image data from self/other peers + struct Avatar_Numbers avatar_numbers; + char zero_array[184 * 184 * 4] = {}; + std::string small_avatar(zero_array, 32 * 32 * 4); + std::string medium_avatar(zero_array, 64 * 64 * 4); + std::string large_avatar(zero_array, 184 * 184 * 4); + + avatar_numbers.smallest = settings->add_image(small_avatar, 32, 32); + avatar_numbers.medium = settings->add_image(medium_avatar, 64, 64); + avatar_numbers.large = settings->add_image(large_avatar, 184, 184); + + avatars[steam_id] = avatar_numbers; + return avatar_numbers; +} + public: static void steam_friends_callback(void *object, Common_Message *msg) { @@ -552,8 +581,10 @@ void ActivateGameOverlayInviteDialog( CSteamID steamIDLobby ) int GetSmallFriendAvatar( CSteamID steamIDFriend ) { PRINT_DEBUG("Steam_Friends::GetSmallFriendAvatar\n"); - ++img_count; - return (img_count * 3) + 1; + //IMPORTANT NOTE: don't change friend avatar numbers for the same friend or else some games endlessly allocate stuff. + std::lock_guard lock(global_mutex); + struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend); + return numbers.smallest; } @@ -561,8 +592,9 @@ int GetSmallFriendAvatar( CSteamID steamIDFriend ) int GetMediumFriendAvatar( CSteamID steamIDFriend ) { PRINT_DEBUG("Steam_Friends::GetMediumFriendAvatar\n"); - ++img_count; - return (img_count * 3) + 2; + std::lock_guard lock(global_mutex); + struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend); + return numbers.medium; } @@ -571,8 +603,9 @@ int GetMediumFriendAvatar( CSteamID steamIDFriend ) int GetLargeFriendAvatar( CSteamID steamIDFriend ) { PRINT_DEBUG("Steam_Friends::GetLargeFriendAvatar\n"); - ++img_count; - return (img_count * 3) + 0; + std::lock_guard lock(global_mutex); + struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend); + return numbers.large; } int GetFriendAvatar( CSteamID steamIDFriend, int eAvatarSize ) @@ -671,19 +704,19 @@ bool SetRichPresence( const char *pchKey, const char *pchValue ) PRINT_DEBUG("Steam_Friends::SetRichPresence %s %s\n", pchKey, pchValue ? pchValue : "NULL"); std::lock_guard lock(global_mutex); if (pchValue) { - #ifdef SHOW_DIALOG_RICH_CONNECT - if (std::string(pchKey) == std::string("connect")) - MessageBox(0, pchValue, pchKey, MB_OK); - #endif - (*us.mutable_rich_presence())[pchKey] = pchValue; + auto prev_value = (*us.mutable_rich_presence()).find(pchKey); + if (prev_value == (*us.mutable_rich_presence()).end() || prev_value->second != pchValue) { + (*us.mutable_rich_presence())[pchKey] = pchValue; + modified = true; + } } else { auto to_remove = us.mutable_rich_presence()->find(pchKey); if (to_remove != us.mutable_rich_presence()->end()) { us.mutable_rich_presence()->erase(to_remove); + modified = true; } } - modified = true; - + return true; } diff --git a/dll/steam_utils.h b/dll/steam_utils.h index 24050246..6f96efb9 100644 --- a/dll/steam_utils.h +++ b/dll/steam_utils.h @@ -82,39 +82,35 @@ const char *GetIPCountry() return "US"; } -static uint32 width_image(int iImage) -{ - if ((iImage % 3) == 1) return 32; - if ((iImage % 3) == 2) return 64; - return 184; -} - // returns true if the image exists, and valid sizes were filled out bool GetImageSize( int iImage, uint32 *pnWidth, uint32 *pnHeight ) { - PRINT_DEBUG("GetImageSize\n"); + PRINT_DEBUG("GetImageSize %i\n", iImage); if (!iImage || !pnWidth || !pnHeight) return false; + auto image = settings->images.find(iImage); + if (image == settings->images.end()) return false; - *pnWidth = width_image(iImage); - *pnHeight = width_image(iImage);; + *pnWidth = image->second.width; + *pnHeight = image->second.height; return true; } - // returns true if the image exists, and the buffer was successfully filled out // results are returned in RGBA format // the destination buffer size should be 4 * height * width * sizeof(char) bool GetImageRGBA( int iImage, uint8 *pubDest, int nDestBufferSize ) { - PRINT_DEBUG("GetImageRGBA\n"); + PRINT_DEBUG("GetImageRGBA %i\n", iImage); if (!iImage || !pubDest || !nDestBufferSize) return false; - unsigned size = width_image(iImage) * width_image(iImage) * 4; + auto image = settings->images.find(iImage); + if (image == settings->images.end()) return false; + + unsigned size = image->second.data.size(); if (nDestBufferSize < size) size = nDestBufferSize; - memset(pubDest, 0xFF, size); + image->second.data.copy((char *)pubDest, nDestBufferSize); return true; } - // returns the IP of the reporting server for valve - currently only used in Source engine games bool GetCSERIPPort( uint32 *unIP, uint16 *usPort ) {