Skip to content

Commit

Permalink
Merge pull request #9 from otavepto/patch-user-stats-icon
Browse files Browse the repository at this point in the history
Implement `Steam_User_Stats::GetAchievementIcon()`
  • Loading branch information
Detanup01 committed Aug 18, 2024
2 parents 5f78184 + 97bec67 commit f1d4ba6
Show file tree
Hide file tree
Showing 36 changed files with 2,585 additions and 18,695 deletions.
2 changes: 1 addition & 1 deletion dll/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const std::chrono::time_point<std::chrono::high_resolution_clock> startup_counte
const std::chrono::time_point<std::chrono::system_clock> startup_time = std::chrono::system_clock::now();

#ifndef EMU_RELEASE_BUILD
dbg_log dbg_logger(get_full_program_path() + "STEAM_LOG.txt");
dbg_log dbg_logger(get_full_program_path() + "STEAM_LOG_" + std::to_string(common_helpers::rand_number(UINT32_MAX)) + ".log");
#endif


Expand Down
10 changes: 8 additions & 2 deletions dll/dll/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,15 @@ class Settings {
std::map<std::string, Leaderboard_config> leaderboards{};
std::map<std::string, Stat_config> stats{};

std::map<size_t, struct Image_Data> images{};

//supported languages
std::set<std::string> supported_languages_set{};
std::string supported_languages{};

public:
constexpr const static int INVALID_IMAGE_HANDLE = 0;

//Depots
std::vector<DepotId_t> depots{};

Expand Down Expand Up @@ -253,6 +257,9 @@ class Settings {
// when a stat that's tied to an achievement gets a new value, should the emu save that progress only if it's higher?
// the stat itself is always saved regardless of that flag, only affects the achievement progress
bool save_only_higher_stat_achievement_progress = true;
// the emulator loads the achievements icons is memory mainly for `ISteamUserStats::GetAchievementIcon()`
// true means load icons lazily when they are requested, otherwise load icons as soon as the interface ISteamUserStats is initialized
bool lazy_load_achievements_icons = true;

// bypass to make SetAchievement() always return true, prevent some games from breaking
bool achievement_bypass = false;
Expand All @@ -265,8 +272,6 @@ class Settings {
// enable owning Steam Applications IDs (mostly builtin apps + dedicated servers)
bool enable_builtin_preowned_ids = false;

std::map<int, struct Image_Data> images{};

//subscribed lobby/group ids
std::set<uint64> subscribed_groups{};
std::vector<Group_Clans> subscribed_groups_clans{};
Expand Down Expand Up @@ -383,6 +388,7 @@ class Settings {

//images
int add_image(const std::string &data, uint32 width, uint32 height);
Image_Data* get_image(int handle);

// overlay auto accept stuff
void acceptAnyOverlayInvites(bool value);
Expand Down
10 changes: 9 additions & 1 deletion dll/dll/steam_user_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public ISteamUserStats
{
public:
static constexpr auto achievements_user_file = "achievements.json";
static constexpr int UNLOADED_ACH_ICON = -1;

private:
template<typename T>
Expand All @@ -94,6 +95,8 @@ public ISteamUserStats
nlohmann::json defined_achievements{};
nlohmann::json user_achievements{};
std::vector<std::string> sorted_achievement_names{};
bool achievements_icons_loaded = false;

std::map<std::string, int32> stats_cache_int{};
std::map<std::string, float> stats_cache_float{};

Expand All @@ -109,6 +112,8 @@ public ISteamUserStats
void load_achievements();
void save_achievements();

int load_ach_icon(nlohmann::json &defined_ach, bool achieved);

nlohmann::detail::iter_impl<nlohmann::json> defined_achievements_find(const std::string &key);
std::string get_value_for_language(const nlohmann::json &json, std::string_view key, std::string_view language);

Expand All @@ -132,6 +137,7 @@ public ISteamUserStats
InternalSetResult<bool> clear_achievement_internal( const char *pchName );

void send_updated_stats();
void load_achievements_icons();
void steam_run_callback();

// requests from server
Expand Down Expand Up @@ -207,7 +213,9 @@ public ISteamUserStats
// specified achievement.
int GetAchievementIcon( const char *pchName );

std::string get_achievement_icon_name( const char *pchName, bool pbAchieved );
int get_achievement_icon_handle( const std::string &ach_name, bool pbAchieved );

std::string get_achievement_icon_name( const char *pchName, bool achieved );


// Get general attributes for an achievement. Accepts the following keys:
Expand Down
15 changes: 7 additions & 8 deletions dll/local_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,9 +859,9 @@ std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_pa
std::vector<image_pixel_t> res{};
int width{}, height{};
image_pixel_t* img = (image_pixel_t*)stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
if (img != nullptr)
{
res.resize(width*height);
PRINT_DEBUG("stbi_load('%s') -> %s", image_path.c_str(), (img ? "loaded" : stbi_failure_reason()));
if (img) {
res.resize(width * height);
std::copy(img, img + width * height, res.begin());

stbi_image_free(img);
Expand All @@ -875,19 +875,18 @@ std::string Local_Storage::load_image_resized(std::string const& image_path, std
{
std::string resized_image{};
const size_t resized_img_size = resolution * resolution * 4;

if (image_path.length() > 0) {
if (image_path.size()) {
int width = 0;
int height = 0;
unsigned char *img = stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
PRINT_DEBUG("stbi_load('%s') -> %s", image_path.c_str(), (img == nullptr ? stbi_failure_reason() : "loaded"));
if (img != nullptr) {
PRINT_DEBUG("stbi_load('%s') -> %s", image_path.c_str(), (img ? "loaded" : stbi_failure_reason()));
if (img) {
std::vector<char> out_resized(resized_img_size);
stbir_resize_uint8(img, width, height, 0, (unsigned char*)&out_resized[0], resolution, resolution, 0, 4);
resized_image = std::string((char*)&out_resized[0], out_resized.size());
stbi_image_free(img);
}
} else if (image_data.length() > 0) {
} else if (image_data.size()) {
std::vector<char> out_resized(resized_img_size);
stbir_resize_uint8((unsigned char*)image_data.c_str(), 184, 184, 0, (unsigned char*)&out_resized[0], resolution, resolution, 0, 4);
resized_image = std::string((char*)&out_resized[0], out_resized.size());
Expand Down
32 changes: 28 additions & 4 deletions dll/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,37 @@ std::map<std::string, Stat_config>::const_iterator Settings::setStatDefiniton(co

int Settings::add_image(const std::string &data, uint32 width, uint32 height)
{
int last = static_cast<int>(images.size()) + 1;
struct Image_Data dt;
auto previous_it = std::find_if(images.begin(), images.end(), [&](const std::pair<const size_t, Image_Data> &item) {
return item.second.data == data
&& item.second.height == height
&& item.second.width == width;
});
if (images.end() != previous_it) {
return static_cast<int>(previous_it->first);
}

struct Image_Data dt{};
dt.width = width;
dt.height = height;
dt.data = data;
images[last] = dt;
return last;

auto new_handle = images.size() + 1; // never return 0, it is a bad handle for most ISteamUserStats APIs
images[new_handle] = dt;

return static_cast<int>(new_handle);
}

Image_Data* Settings::get_image(int handle)
{
if (INVALID_IMAGE_HANDLE == handle) {
return nullptr;
}

auto image_it = images.find(handle);
if (images.end() == image_it) {
return nullptr;
}
return &image_it->second;
}


Expand Down
32 changes: 20 additions & 12 deletions dll/settings_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1364,18 +1364,6 @@ static void parse_simple_features(class Settings *settings_client, class Setting
settings_client->steam_deck = ini.GetBoolValue("main::general", "steam_deck", settings_client->steam_deck);
settings_server->steam_deck = ini.GetBoolValue("main::general", "steam_deck", settings_server->steam_deck);

settings_client->disable_leaderboards_create_unknown = ini.GetBoolValue("main::general", "disable_leaderboards_create_unknown", settings_client->disable_leaderboards_create_unknown);
settings_server->disable_leaderboards_create_unknown = ini.GetBoolValue("main::general", "disable_leaderboards_create_unknown", settings_server->disable_leaderboards_create_unknown);

settings_client->allow_unknown_stats = ini.GetBoolValue("main::general", "allow_unknown_stats", settings_client->allow_unknown_stats);
settings_server->allow_unknown_stats = ini.GetBoolValue("main::general", "allow_unknown_stats", settings_server->allow_unknown_stats);

settings_client->stat_achievement_progress_functionality = ini.GetBoolValue("main::general", "stat_achievement_progress_functionality", settings_client->stat_achievement_progress_functionality);
settings_server->stat_achievement_progress_functionality = ini.GetBoolValue("main::general", "stat_achievement_progress_functionality", settings_server->stat_achievement_progress_functionality);

settings_client->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::general", "save_only_higher_stat_achievement_progress", settings_client->save_only_higher_stat_achievement_progress);
settings_server->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::general", "save_only_higher_stat_achievement_progress", settings_server->save_only_higher_stat_achievement_progress);

settings_client->immediate_gameserver_stats = ini.GetBoolValue("main::general", "immediate_gameserver_stats", settings_client->immediate_gameserver_stats);
settings_server->immediate_gameserver_stats = ini.GetBoolValue("main::general", "immediate_gameserver_stats", settings_server->immediate_gameserver_stats);

Expand Down Expand Up @@ -1420,6 +1408,25 @@ static void parse_simple_features(class Settings *settings_client, class Setting
settings_server->enable_builtin_preowned_ids = ini.GetBoolValue("main::misc", "enable_steam_preowned_ids", settings_server->enable_builtin_preowned_ids);
}

// [main::stats]
static void parse_stats_features(class Settings *settings_client, class Settings *settings_server)
{
settings_client->disable_leaderboards_create_unknown = ini.GetBoolValue("main::stats", "disable_leaderboards_create_unknown", settings_client->disable_leaderboards_create_unknown);
settings_server->disable_leaderboards_create_unknown = ini.GetBoolValue("main::stats", "disable_leaderboards_create_unknown", settings_server->disable_leaderboards_create_unknown);

settings_client->allow_unknown_stats = ini.GetBoolValue("main::stats", "allow_unknown_stats", settings_client->allow_unknown_stats);
settings_server->allow_unknown_stats = ini.GetBoolValue("main::stats", "allow_unknown_stats", settings_server->allow_unknown_stats);

settings_client->stat_achievement_progress_functionality = ini.GetBoolValue("main::stats", "stat_achievement_progress_functionality", settings_client->stat_achievement_progress_functionality);
settings_server->stat_achievement_progress_functionality = ini.GetBoolValue("main::stats", "stat_achievement_progress_functionality", settings_server->stat_achievement_progress_functionality);

settings_client->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::stats", "save_only_higher_stat_achievement_progress", settings_client->save_only_higher_stat_achievement_progress);
settings_server->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::stats", "save_only_higher_stat_achievement_progress", settings_server->save_only_higher_stat_achievement_progress);

settings_client->lazy_load_achievements_icons = ini.GetBoolValue("main::stats", "lazy_load_achievements_icons", settings_client->lazy_load_achievements_icons);
settings_server->lazy_load_achievements_icons = ini.GetBoolValue("main::stats", "lazy_load_achievements_icons", settings_server->lazy_load_achievements_icons);
}



static std::map<SettingsItf, std::string> old_itfs_map{};
Expand Down Expand Up @@ -1673,6 +1680,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
settings_server->set_supported_languages(supported_languages);

parse_simple_features(settings_client, settings_server);
parse_stats_features(settings_client, settings_server);

parse_dlc(settings_client, settings_server);
parse_installed_app_Ids(settings_client, settings_server);
Expand Down
10 changes: 8 additions & 2 deletions dll/steam_friends.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1280,9 +1280,15 @@ void Steam_Friends::Callback(Common_Message *msg)
f->set_name(settings->get_local_name());
f->set_appid(settings->get_local_game_id().AppID());
f->set_lobby_id(settings->get_lobby().ConvertToUint64());

int avatar_number = GetLargeFriendAvatar(settings->get_local_steam_id());
if (settings->images[avatar_number].data.length() > 0) f->set_avatar(settings->images[avatar_number].data);
else f->set_avatar("");
auto avatar_info = settings->get_image(avatar_number);
if (avatar_info && avatar_info->data.size()) {
f->set_avatar(avatar_info->data);
} else {
f->set_avatar("");
}

msg_.set_allocated_friend_(f);
network->sendTo(&msg_, true);
}
Expand Down
Loading

0 comments on commit f1d4ba6

Please sign in to comment.