diff --git a/dll/dll/settings.h b/dll/dll/settings.h index 90c86964..fc3b7719 100644 --- a/dll/dll/settings.h +++ b/dll/dll/settings.h @@ -229,6 +229,9 @@ public: // can use GC token for generation bool use_gc_token = false; + // allow stats not defined by the user? + bool allow_unknown_stats = false; + // bypass to make SetAchievement() always return true, prevent some games from breaking bool achievement_bypass = false; @@ -352,7 +355,7 @@ public: //stats const std::map& getStats() const; - void setStatDefiniton(const std::string &name, const struct Stat_config &stat_config); + std::map::const_iterator setStatDefiniton(const std::string &name, const struct Stat_config &stat_config); //images int add_image(const std::string &data, uint32 width, uint32 height); diff --git a/dll/settings.cpp b/dll/settings.cpp index 90ab622e..2093c0d5 100644 --- a/dll/settings.cpp +++ b/dll/settings.cpp @@ -344,9 +344,10 @@ const std::map& Settings::getStats() const return stats; } -void Settings::setStatDefiniton(const std::string &name, const struct Stat_config &stat_config) +std::map::const_iterator Settings::setStatDefiniton(const std::string &name, const struct Stat_config &stat_config) { - stats[common_helpers::ascii_to_lowercase(name)] = stat_config; + auto ins_it = stats.insert_or_assign(common_helpers::ascii_to_lowercase(name), stat_config); + return ins_it.first; } diff --git a/dll/settings_parser.cpp b/dll/settings_parser.cpp index 8740242e..28c2dd89 100644 --- a/dll/settings_parser.cpp +++ b/dll/settings_parser.cpp @@ -1287,6 +1287,9 @@ static void parse_simple_features(class Settings *settings_client, class Setting 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->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); diff --git a/dll/steam_user_stats.cpp b/dll/steam_user_stats.cpp index eaea5b8e..a629f632 100644 --- a/dll/steam_user_stats.cpp +++ b/dll/steam_user_stats.cpp @@ -433,6 +433,13 @@ Steam_User_Stats::InternalSetResult Steam_User_Stats::set_stat_internal( const auto &stats_config = settings->getStats(); auto stats_data = stats_config.find(stat_name); + if (stats_config.end() == stats_data && settings->allow_unknown_stats) { + Stat_config cfg{}; + cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_INT; + cfg.default_value_int = 0; + stats_data = settings->setStatDefiniton(stat_name, cfg); + } + if (stats_config.end() == stats_data) return result; if (stats_data->second.type != GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return result; @@ -480,6 +487,13 @@ Steam_User_Stats::InternalSetResultgetStats(); auto stats_data = stats_config.find(stat_name); + if (stats_config.end() == stats_data && settings->allow_unknown_stats) { + Stat_config cfg{}; + cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT; + cfg.default_value_float = 0; + stats_data = settings->setStatDefiniton(stat_name, cfg); + } + if (stats_config.end() == stats_data) return result; if (stats_data->second.type == GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return result; @@ -528,6 +542,13 @@ Steam_User_Stats::InternalSetResultgetStats(); auto stats_data = stats_config.find(stat_name); + if (stats_config.end() == stats_data && settings->allow_unknown_stats) { + Stat_config cfg{}; + cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_AVGRATE; + cfg.default_value_float = 0; + stats_data = settings->setStatDefiniton(stat_name, cfg); + } + if (stats_config.end() == stats_data) return result; if (stats_data->second.type == GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return result; @@ -822,6 +843,13 @@ bool Steam_User_Stats::GetStat( const char *pchName, int32 *pData ) const auto &stats_config = settings->getStats(); auto stats_data = stats_config.find(stat_name); + if (stats_config.end() == stats_data && settings->allow_unknown_stats) { + Stat_config cfg{}; + cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_INT; + cfg.default_value_int = 0; + stats_data = settings->setStatDefiniton(stat_name, cfg); + } + if (stats_config.end() == stats_data) return false; if (stats_data->second.type != GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return false; @@ -854,6 +882,13 @@ bool Steam_User_Stats::GetStat( const char *pchName, float *pData ) const auto &stats_config = settings->getStats(); auto stats_data = stats_config.find(stat_name); + if (stats_config.end() == stats_data && settings->allow_unknown_stats) { + Stat_config cfg{}; + cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT; + cfg.default_value_float = 0; + stats_data = settings->setStatDefiniton(stat_name, cfg); + } + if (stats_config.end() == stats_data) return false; if (stats_data->second.type == GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return false; diff --git a/post_build/steam_settings.EXAMPLE/configs.main.EXAMPLE.ini b/post_build/steam_settings.EXAMPLE/configs.main.EXAMPLE.ini index 4c6164c3..f1f30b5b 100644 --- a/post_build/steam_settings.EXAMPLE/configs.main.EXAMPLE.ini +++ b/post_build/steam_settings.EXAMPLE/configs.main.EXAMPLE.ini @@ -14,6 +14,10 @@ enable_account_avatar=0 # prevent Steam_User_Stats::FindLeaderboard() from always succeeding and creating the unknown leaderboard # not recommended to disable this disable_leaderboards_create_unknown=0 +# the emu will only save/update stats defined by the user, unknown stats requested or updated by the game will be rejected +# set this to 1 to allow unknown stats +# default=0 +allow_unknown_stats=0 # synchronize user stats/achievements with game servers as soon as possible instead of caching them until the next call to `Steam_RunCallbacks()` # not recommended immediate_gameserver_stats=0