* always trigger UserStatsStored_t and UserAchievementStored_t callbacks in Steam_User_Stats::IndicateAchievementProgress() even if value wasn't updated, games my halt otherwise

* return false in Steam_User_Stats::GetAchievementProgressLimits() if the achievement has no progress
* share progress info with gameservers
This commit is contained in:
otavepto 2024-06-18 16:37:04 +03:00
parent aa791b5256
commit cd21b54e6b
2 changed files with 76 additions and 10 deletions

View File

@ -236,7 +236,13 @@ message GameServerStats_Messages {
optional AvgStatInfo value_avg = 4; // only set when type != INT
}
message AchievementInfo {
// progress is always sent from user to server, not the opposite
message Progress {
float progress = 1;
float max_progress = 2;
}
bool achieved = 1;
optional Progress progress = 2;
}
// --- requests & responses objects

View File

@ -1164,14 +1164,19 @@ bool Steam_User_Stats::IndicateAchievementProgress( const char *pchName, uint32
if (achieved) return false;
// save new progress
bool value_updated = false;
try {
auto old_progress = user_achievements.value(actual_ach_name, nlohmann::json{}).value("progress", ~nCurProgress);
if (old_progress == nCurProgress) return true;
user_achievements[actual_ach_name]["progress"] = nCurProgress;
user_achievements[actual_ach_name]["max_progress"] = nMaxProgress;
save_achievements();
overlay->AddAchievementNotification(actual_ach_name, user_achievements[actual_ach_name], true);
if (old_progress != nCurProgress) {
user_achievements[actual_ach_name]["progress"] = nCurProgress;
user_achievements[actual_ach_name]["max_progress"] = nMaxProgress;
save_achievements();
value_updated = true;
overlay->AddAchievementNotification(actual_ach_name, user_achievements[actual_ach_name], true);
}
} catch (...) {}
{
@ -1191,6 +1196,20 @@ bool Steam_User_Stats::IndicateAchievementProgress( const char *pchName, uint32
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
// progress is always sent from user to server, not the opposite
if (value_updated && !settings->disable_sharing_stats_with_gameserver) {
auto &new_ach = (*pending_server_updates.mutable_user_achievements())[actual_ach_name];
new_ach.set_achieved(false);
auto progress_msg = new GameServerStats_Messages::AchievementInfo::Progress();
progress_msg->set_progress((float)nCurProgress);
progress_msg->set_max_progress((float)nMaxProgress);
new_ach.set_allocated_progress(progress_msg);
if (settings->immediate_gameserver_stats) send_updated_stats();
}
return true;
}
@ -1902,7 +1921,7 @@ bool Steam_User_Stats::GetAchievementProgressLimits( const char *pchName, float
if (!pchName) return false;
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
auto it = defined_achievements.end();
try {
it = defined_achievements_find(pchName);
}
@ -1916,13 +1935,40 @@ bool Steam_User_Stats::GetAchievementProgressLimits( const char *pchName, float
std::string pch_name = it->value("name", std::string());
auto ach = user_achievements.find(pch_name);
if (user_achievements.end() != ach) {
if (pfMinProgress) *pfMinProgress = ach->value("progress", static_cast<float>(0));
if (pfMaxProgress) *pfMaxProgress = ach->value("max_progress", static_cast<float>(0));
auto it_progress = ach->find("progress");
auto it_max_progress = ach->find("max_progress");
if (ach->end() == it_progress || ach->end() == it_max_progress) return false;
if (pfMinProgress) {
try {
if (it_progress->is_number()) {
*pfMinProgress = it_progress->get<float>();
} else {
auto s_ptr = it_progress->get_ptr<std::string*>();
if (s_ptr) {
*pfMinProgress = std::stof(*s_ptr);
}
}
}catch(...){}
}
if (pfMaxProgress) {
try {
if (it_max_progress->is_number()) {
*pfMaxProgress = it_max_progress->get<float>();
} else {
auto s_ptr = it_max_progress->get_ptr<std::string*>();
if (s_ptr) {
*pfMaxProgress = std::stof(*s_ptr);
}
}
}catch(...){}
}
return true;
}
}
catch (...) {}
return true;
return false;
}
@ -2011,9 +2057,23 @@ void Steam_User_Stats::network_stats_initial(Common_Message *msg)
for (const auto &ach : defined_achievements) {
const std::string &name = static_cast<const std::string &>( ach.value("name", std::string()) );
auto &this_ach = achievements_map[name];
// achieved or not
bool achieved = false;
GetAchievement(name.c_str(), &achieved);
this_ach.set_achieved(achieved);
// progress
if (!achieved) {
float progress = 0;
float max_progress = 0;
if (GetAchievementProgressLimits(name.c_str(), &progress, &max_progress) && max_progress > 0) {
auto progress_msg = new GameServerStats_Messages_AchievementInfo_Progress();
progress_msg->set_progress(progress);
progress_msg->set_max_progress(max_progress);
this_ach.set_allocated_progress(progress_msg);
}
}
}
auto initial_stats_msg = new GameServerStats_Messages::InitialAllStats();