more accurate implementation for callbacks and call results in UserStats and GameServerStats interfaces

This commit is contained in:
otavepto 2024-04-11 06:40:29 +02:00
parent 1b18338579
commit 4d895b63b0
9 changed files with 182 additions and 66 deletions

View File

@ -1,5 +1,11 @@
## 2024/4/11 ## 2024/4/11
* more accurate implementation for callbacks and call results in `UserStats` and `GameServerStats` interfaces
---
## 2024/4/11
* **[breaking]** load overlay audio from `sounds` subfolder, either from the local game settings folder `steam_settings/sounds`, * **[breaking]** load overlay audio from `sounds` subfolder, either from the local game settings folder `steam_settings/sounds`,
or from the global settings folder `Goldberg SteamEmu Settings/settings/sounds` or from the global settings folder `Goldberg SteamEmu Settings/settings/sounds`
* allow loading the overlay fonts from the global settings folder `Goldberg SteamEmu Settings/settings/fonts` * allow loading the overlay fonts from the global settings folder `Goldberg SteamEmu Settings/settings/fonts`

View File

@ -87,15 +87,15 @@ struct Steam_Call_Result {
return callbacks.size() > 0; return callbacks.size() > 0;
} }
SteamAPICall_t api_call; SteamAPICall_t api_call{};
std::vector<class CCallbackBase *> callbacks; std::vector<class CCallbackBase *> callbacks{};
std::vector<char> result; std::vector<char> result{};
bool to_delete = false; bool to_delete = false;
bool reserved = false; bool reserved = false;
std::chrono::high_resolution_clock::time_point created; std::chrono::high_resolution_clock::time_point created{};
double run_in; double run_in{};
bool run_call_completed_cb; bool run_call_completed_cb{};
int iCallback; int iCallback{};
}; };
unsigned generate_account_id(); unsigned generate_account_id();
@ -113,8 +113,8 @@ bool file_exists_(const std::string &full_path);
unsigned int file_size_(const std::string &full_path); unsigned int file_size_(const std::string &full_path);
class SteamCallResults { class SteamCallResults {
std::vector<struct Steam_Call_Result> callresults; std::vector<struct Steam_Call_Result> callresults{};
std::vector<class CCallbackBase *> completed_callbacks; std::vector<class CCallbackBase *> completed_callbacks{};
void (*cb_all)(std::vector<char> result, int callback) = nullptr; void (*cb_all)(std::vector<char> result, int callback) = nullptr;
public: public:
@ -309,13 +309,14 @@ public:
}; };
struct Steam_Call_Back { struct Steam_Call_Back {
std::vector<class CCallbackBase *> callbacks; std::vector<class CCallbackBase *> callbacks{};
std::vector<std::vector<char>> results; std::vector<std::vector<char>> results{};
}; };
class SteamCallBacks { class SteamCallBacks {
std::map<int, struct Steam_Call_Back> callbacks; std::map<int, struct Steam_Call_Back> callbacks{};
SteamCallResults *results; SteamCallResults *results{};
public: public:
SteamCallBacks(SteamCallResults *results) { SteamCallBacks(SteamCallResults *results) {
this->results = results; this->results = results;
@ -352,7 +353,7 @@ public:
} }
} }
std::vector<char> temp; std::vector<char> temp{};
temp.resize(size); temp.resize(size);
memcpy(&(temp[0]), result, size); memcpy(&(temp[0]), result, size);
callbacks[iCallback].results.push_back(temp); callbacks[iCallback].results.push_back(temp);
@ -401,12 +402,12 @@ public:
}; };
struct RunCBs { struct RunCBs {
void (*function)(void *object); void (*function)(void *object) = nullptr;
void *object; void *object{};
}; };
class RunEveryRunCB { class RunEveryRunCB {
std::vector<struct RunCBs> cbs; std::vector<struct RunCBs> cbs{};
public: public:
void add(void (*cb)(void *object), void *object) { void add(void (*cb)(void *object), void *object) {
remove(cb, object); remove(cb, object);

View File

@ -10,11 +10,12 @@ public ISteamApps006,
public ISteamApps007, public ISteamApps007,
public ISteamApps public ISteamApps
{ {
Settings *settings; Settings *settings{};
class SteamCallResults *callback_results; class SteamCallResults *callback_results{};
class SteamCallBacks *callbacks{};
public: public:
Steam_Apps(Settings *settings, class SteamCallResults *callback_results); Steam_Apps(Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks);
// returns 0 if the key does not exist // returns 0 if the key does not exist
// this may be true on first call, since the app data may not be cached locally yet // this may be true on first call, since the app data may not be cached locally yet

View File

@ -45,10 +45,10 @@ struct Steam_Leaderboard {
}; };
struct achievement_trigger { struct achievement_trigger {
std::string name; std::string name{};
std::string value_operation; std::string value_operation{};
std::string min_value; std::string min_value{};
std::string max_value; std::string max_value{};
bool check_triggered(float stat) { bool check_triggered(float stat) {
try { try {
@ -109,6 +109,10 @@ private:
std::map<std::string, std::vector<achievement_trigger>> achievement_stat_trigger{}; std::map<std::string, std::vector<achievement_trigger>> achievement_stat_trigger{};
// triggered when an achievement is unlocked
// https://partner.steamgames.com/doc/api/ISteamUserStats#StoreStats
std::map<std::string, UserAchievementStored_t> store_stats_trigger{};
GameServerStats_Messages::AllStats pending_server_updates{}; GameServerStats_Messages::AllStats pending_server_updates{};

View File

@ -18,10 +18,11 @@
#include "dll/steam_apps.h" #include "dll/steam_apps.h"
#include "sha/sha1.hpp" #include "sha/sha1.hpp"
Steam_Apps::Steam_Apps(Settings *settings, class SteamCallResults *callback_results) Steam_Apps::Steam_Apps(Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks)
{ {
this->settings = settings; this->settings = settings;
this->callback_results = callback_results; this->callback_results = callback_results;
this->callbacks = callbacks;
} }
// returns 0 if the key does not exist // returns 0 if the key does not exist
@ -168,9 +169,15 @@ bool Steam_Apps::BGetDLCDataByIndex( int iDLC, AppId_t *pAppID, bool *pbAvailabl
// Install/Uninstall control for optional DLC // Install/Uninstall control for optional DLC
void Steam_Apps::InstallDLC( AppId_t nAppID ) void Steam_Apps::InstallDLC( AppId_t nAppID )
{ {
PRINT_DEBUG_ENTRY(); PRINT_DEBUG_TODO();
// we lock here because the API is supposed to modify the DLC list // we lock here because the API is supposed to modify the DLC list
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (settings->hasDLC(nAppID)) {
DlcInstalled_t data{};
data.m_nAppID = nAppID;
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.01);
}
} }
void Steam_Apps::UninstallDLC( AppId_t nAppID ) void Steam_Apps::UninstallDLC( AppId_t nAppID )
@ -226,7 +233,7 @@ void Steam_Apps::RequestAppProofOfPurchaseKey( AppId_t nAppID )
FillProofOfPurchaseKey(data, nAppID, false); FillProofOfPurchaseKey(data, nAppID, false);
} }
callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
} }
// returns current beta branch name, 'public' is the default branch // returns current beta branch name, 'public' is the default branch
@ -422,7 +429,9 @@ SteamAPICall_t Steam_Apps::GetFileDetails( const char* pszFileName )
data.m_eResult = k_EResultFileNotFound; data.m_eResult = k_EResultFileNotFound;
} }
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
// Get command line if game was launched via Steam URL, e.g. steam://run/<appid>//<command line>/. // Get command line if game was launched via Steam URL, e.g. steam://run/<appid>//<command line>/.
@ -463,3 +472,22 @@ bool Steam_Apps::SetDlcContext( AppId_t nAppID )
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
return true; return true;
} }
#ifdef _PS3
// Result returned in a RegisterActivationCodeResponse_t callresult
SteamAPICall_t Steam_Apps::RegisterActivationCode( const char *pchActivationCode )
{
PRINT_DEBUG("%s", pchActivationCode);
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchActivationCode) return
RegisterActivationCodeResponse_t data{};
data.m_eResult = ERegisterActivationCodeResult::k_ERegisterActivationCodeResultOK;
// data.m_unPackageRegistered = 0; // TODO set this
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
}
#endif

View File

@ -106,7 +106,7 @@ Steam_Client::Steam_Client()
steam_matchmaking = new Steam_Matchmaking(settings_client, network, callback_results_client, callbacks_client, run_every_runcb); steam_matchmaking = new Steam_Matchmaking(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_matchmaking_servers = new Steam_Matchmaking_Servers(settings_client, network); steam_matchmaking_servers = new Steam_Matchmaking_Servers(settings_client, network);
steam_user_stats = new Steam_User_Stats(settings_client, network, local_storage, callback_results_client, callbacks_client, run_every_runcb, steam_overlay); steam_user_stats = new Steam_User_Stats(settings_client, network, local_storage, callback_results_client, callbacks_client, run_every_runcb, steam_overlay);
steam_apps = new Steam_Apps(settings_client, callback_results_client); steam_apps = new Steam_Apps(settings_client, callback_results_client, callbacks_client);
steam_networking = new Steam_Networking(settings_client, network, callbacks_client, run_every_runcb); steam_networking = new Steam_Networking(settings_client, network, callbacks_client, run_every_runcb);
steam_remote_storage = new Steam_Remote_Storage(settings_client, ugc_bridge, local_storage, callback_results_client); steam_remote_storage = new Steam_Remote_Storage(settings_client, ugc_bridge, local_storage, callback_results_client);
steam_screenshots = new Steam_Screenshots(local_storage, callbacks_client); steam_screenshots = new Steam_Screenshots(local_storage, callbacks_client);
@ -139,7 +139,7 @@ Steam_Client::Steam_Client()
steam_gameserver_http = new Steam_HTTP(settings_server, network, callback_results_server, callbacks_server); steam_gameserver_http = new Steam_HTTP(settings_server, network, callback_results_server, callbacks_server);
steam_gameserver_inventory = new Steam_Inventory(settings_server, callback_results_server, callbacks_server, run_every_runcb, local_storage); steam_gameserver_inventory = new Steam_Inventory(settings_server, callback_results_server, callbacks_server, run_every_runcb, local_storage);
steam_gameserver_ugc = new Steam_UGC(settings_server, ugc_bridge, local_storage, callback_results_server, callbacks_server); steam_gameserver_ugc = new Steam_UGC(settings_server, ugc_bridge, local_storage, callback_results_server, callbacks_server);
steam_gameserver_apps = new Steam_Apps(settings_server, callback_results_server); steam_gameserver_apps = new Steam_Apps(settings_server, callback_results_server, callbacks_server);
steam_gameserver_networking_sockets = new Steam_Networking_Sockets(settings_server, network, callback_results_server, callbacks_server, run_every_runcb, steam_networking_sockets->get_shared_between_client_server()); steam_gameserver_networking_sockets = new Steam_Networking_Sockets(settings_server, network, callback_results_server, callbacks_server, run_every_runcb, steam_networking_sockets->get_shared_between_client_server());
steam_gameserver_networking_sockets_serialized = new Steam_Networking_Sockets_Serialized(settings_server, network, callback_results_server, callbacks_server, run_every_runcb); steam_gameserver_networking_sockets_serialized = new Steam_Networking_Sockets_Serialized(settings_server, network, callback_results_server, callbacks_server, run_every_runcb);
steam_gameserver_networking_messages = new Steam_Networking_Messages(settings_server, network, callback_results_server, callbacks_server, run_every_runcb); steam_gameserver_networking_messages = new Steam_Networking_Messages(settings_server, network, callback_results_server, callbacks_server, run_every_runcb);

View File

@ -639,14 +639,14 @@ bool Steam_GameServer::RequestUserGroupStatus( CSteamID steamIDUser, CSteamID st
// they will be removed in a future version of the SDK // they will be removed in a future version of the SDK
void Steam_GameServer::GetGameplayStats( ) void Steam_GameServer::GetGameplayStats( )
{ {
PRINT_DEBUG_ENTRY(); PRINT_DEBUG_TODO();
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
} }
STEAM_CALL_RESULT( GSReputation_t ) STEAM_CALL_RESULT( GSReputation_t )
SteamAPICall_t Steam_GameServer::GetServerReputation() SteamAPICall_t Steam_GameServer::GetServerReputation()
{ {
PRINT_DEBUG_ENTRY(); PRINT_DEBUG_TODO();
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
return 0; return 0;
} }

View File

@ -121,7 +121,10 @@ SteamAPICall_t Steam_GameServerStats::RequestUserStats( CSteamID steamIDUser )
GSStatsReceived_t data_bad{}; GSStatsReceived_t data_bad{};
data_bad.m_eResult = EResult::k_EResultFail; data_bad.m_eResult = EResult::k_EResultFail;
data_bad.m_steamIDUser = steamIDUser; data_bad.m_steamIDUser = steamIDUser;
return callback_results->addCallResult(data_bad.k_iCallback, &data_bad, sizeof(data_bad));
auto ret = callback_results->addCallResult(data_bad.k_iCallback, &data_bad, sizeof(data_bad));
callbacks->addCBResult(data_bad.k_iCallback, &data_bad, sizeof(data_bad));
return ret;
} }
struct RequestAllStats new_request{}; struct RequestAllStats new_request{};
@ -335,7 +338,9 @@ SteamAPICall_t Steam_GameServerStats::StoreUserStats( CSteamID steamIDUser )
GSStatsStored_t data_bad{}; GSStatsStored_t data_bad{};
data_bad.m_eResult = EResult::k_EResultFail; data_bad.m_eResult = EResult::k_EResultFail;
data_bad.m_steamIDUser = steamIDUser; data_bad.m_steamIDUser = steamIDUser;
return callback_results->addCallResult(data_bad.k_iCallback, &data_bad, sizeof(data_bad)); auto ret = callback_results->addCallResult(data_bad.k_iCallback, &data_bad, sizeof(data_bad));
callbacks->addCBResult(data_bad.k_iCallback, &data_bad, sizeof(data_bad));
return ret;
} }
GSStatsStored_t data{}; GSStatsStored_t data{};
@ -346,7 +351,10 @@ SteamAPICall_t Steam_GameServerStats::StoreUserStats( CSteamID steamIDUser )
data.m_eResult = EResult::k_EResultFail; data.m_eResult = EResult::k_EResultFail;
} }
data.m_steamIDUser = steamIDUser; data.m_steamIDUser = steamIDUser;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.01);
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.01);
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.01);
return ret;
} }
@ -365,7 +373,9 @@ void Steam_GameServerStats::remove_timedout_userstats_requests()
GSStatsReceived_t data{}; GSStatsReceived_t data{};
data.m_eResult = k_EResultTimeout; data.m_eResult = k_EResultTimeout;
data.m_steamIDUser = pendReq.steamIDUser; data.m_steamIDUser = pendReq.steamIDUser;
callback_results->addCallResult(pendReq.steamAPICall, data.k_iCallback, &data, sizeof(data)); callback_results->addCallResult(pendReq.steamAPICall, data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
PRINT_DEBUG("RequestUserStats timeout, %llu", pendReq.steamIDUser.ConvertToUint64()); PRINT_DEBUG("RequestUserStats timeout, %llu", pendReq.steamIDUser.ConvertToUint64());
} }
@ -502,7 +512,9 @@ void Steam_GameServerStats::network_callback_initial_stats(Common_Message *msg)
GSStatsReceived_t data{}; GSStatsReceived_t data{};
data.m_eResult = EResult::k_EResultOK; data.m_eResult = EResult::k_EResultOK;
data.m_steamIDUser = user_steamid; data.m_steamIDUser = user_steamid;
callback_results->addCallResult(it->steamAPICall, data.k_iCallback, &data, sizeof(data)); callback_results->addCallResult(it->steamAPICall, data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
PRINT_DEBUG("server got all player stats %llu: %zu stats, %zu achievements", PRINT_DEBUG("server got all player stats %llu: %zu stats, %zu achievements",
user_steamid, all_users_data[user_steamid].stats.size(), all_users_data[user_steamid].achievements.size() user_steamid, all_users_data[user_steamid].stats.size(), all_users_data[user_steamid].achievements.size()
@ -592,7 +604,9 @@ void Steam_GameServerStats::network_callback_low_level(Common_Message *msg)
GSStatsReceived_t data{}; GSStatsReceived_t data{};
data.m_eResult = k_EResultTimeout; data.m_eResult = k_EResultTimeout;
data.m_steamIDUser = it_rm->steamIDUser; data.m_steamIDUser = it_rm->steamIDUser;
callback_results->addCallResult(it_rm->steamAPICall, data.k_iCallback, &data, sizeof(data)); callback_results->addCallResult(it_rm->steamAPICall, data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
PRINT_DEBUG("RequestUserStats timeout, %llu", it_rm->steamIDUser.ConvertToUint64()); PRINT_DEBUG("RequestUserStats timeout, %llu", it_rm->steamIDUser.ConvertToUint64());
it_rm = pending_RequestUserStats.erase(it_rm); it_rm = pending_RequestUserStats.erase(it_rm);

View File

@ -543,41 +543,59 @@ Steam_User_Stats::InternalSetResult<bool> Steam_User_Stats::set_achievement_inte
if (!pchName) return result; if (!pchName) return result;
std::string org_name(pchName);
if (settings->achievement_bypass) { if (settings->achievement_bypass) {
auto &trig = store_stats_trigger[common_helpers::to_lower(org_name)];
trig.m_bGroupAchievement = false;
trig.m_nCurProgress = 100;
trig.m_nGameID = settings->get_local_game_id().ToUint64();
trig.m_nMaxProgress = 100;
memset(trig.m_rgchAchievementName, 0, sizeof(trig.m_rgchAchievementName));
org_name.copy(trig.m_rgchAchievementName, sizeof(trig.m_rgchAchievementName) - 1);
result.success = true; result.success = true;
return result; return result;
} }
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end(); nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
try { try {
it = defined_achievements_find(pchName); it = defined_achievements_find(org_name);
} catch(...) { } } catch(...) { }
if (defined_achievements.end() == it) return result; if (defined_achievements.end() == it) return result;
result.current_val = true; result.current_val = true;
result.internal_name = pchName; result.internal_name = org_name;
result.success = true; result.success = true;
try { try {
std::string pch_name = it->value("name", std::string()); std::string internal_name = it->value("name", std::string());
result.internal_name = pch_name; result.internal_name = internal_name;
auto ach = user_achievements.find(pch_name); auto ach = user_achievements.find(internal_name);
if (user_achievements.end() == ach || ach->value("earned", false) == false) { if (user_achievements.end() == ach || ach->value("earned", false) == false) {
user_achievements[pch_name]["earned"] = true; user_achievements[internal_name]["earned"] = true;
user_achievements[pch_name]["earned_time"] = user_achievements[internal_name]["earned_time"] =
std::chrono::duration_cast<std::chrono::duration<uint32>>(std::chrono::system_clock::now().time_since_epoch()).count(); std::chrono::duration_cast<std::chrono::duration<uint32>>(std::chrono::system_clock::now().time_since_epoch()).count();
save_achievements(); save_achievements();
result.notify_server = !settings->disable_sharing_stats_with_gameserver; result.notify_server = !settings->disable_sharing_stats_with_gameserver;
if(!settings->disable_overlay) overlay->AddAchievementNotification(it.value()); if (!settings->disable_overlay) overlay->AddAchievementNotification(it.value());
} }
} catch (...) {} } catch (...) {}
auto &trig = store_stats_trigger[common_helpers::to_lower(org_name)];
trig.m_bGroupAchievement = false;
trig.m_nCurProgress = 100;
trig.m_nGameID = settings->get_local_game_id().ToUint64();
trig.m_nMaxProgress = 100;
memset(trig.m_rgchAchievementName, 0, sizeof(trig.m_rgchAchievementName));
org_name.copy(trig.m_rgchAchievementName, sizeof(trig.m_rgchAchievementName) - 1);
return result; return result;
} }
@ -589,30 +607,32 @@ Steam_User_Stats::InternalSetResult<bool> Steam_User_Stats::clear_achievement_in
if (!pchName) return result; if (!pchName) return result;
std::string org_name(pchName);
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end(); nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
try { try {
it = defined_achievements_find(pchName); it = defined_achievements_find(org_name);
} catch(...) { } } catch(...) { }
if (defined_achievements.end() == it) return result; if (defined_achievements.end() == it) return result;
result.current_val = false; result.current_val = false;
result.internal_name = pchName; result.internal_name = org_name;
result.success = true; result.success = true;
try { try {
std::string pch_name = it->value("name", std::string()); std::string internal_name = it->value("name", std::string());
result.internal_name = pch_name; result.internal_name = internal_name;
auto ach = user_achievements.find(pch_name); auto ach = user_achievements.find(internal_name);
// assume "earned" is true in case the json obj exists, but the key is absent // assume "earned" is true in case the json obj exists, but the key is absent
// assume "earned_time" is UINT32_MAX in case the json obj exists, but the key is absent // assume "earned_time" is UINT32_MAX in case the json obj exists, but the key is absent
if (user_achievements.end() == ach || if (user_achievements.end() == ach ||
ach->value("earned", true) == true || ach->value("earned", true) == true ||
ach->value("earned_time", static_cast<uint32>(UINT32_MAX)) == UINT32_MAX) { ach->value("earned_time", static_cast<uint32>(UINT32_MAX)) == UINT32_MAX) {
user_achievements[pch_name]["earned"] = false; user_achievements[internal_name]["earned"] = false;
user_achievements[pch_name]["earned_time"] = static_cast<uint32>(0); user_achievements[internal_name]["earned_time"] = static_cast<uint32>(0);
save_achievements(); save_achievements();
result.notify_server = !settings->disable_sharing_stats_with_gameserver; result.notify_server = !settings->disable_sharing_stats_with_gameserver;
@ -620,6 +640,8 @@ Steam_User_Stats::InternalSetResult<bool> Steam_User_Stats::clear_achievement_in
} }
} catch (...) {} } catch (...) {}
store_stats_trigger.erase(common_helpers::to_lower(org_name));
return result; return result;
} }
@ -983,6 +1005,11 @@ bool Steam_User_Stats::StoreStats()
data.m_nGameID = settings->get_local_game_id().ToUint64(); data.m_nGameID = settings->get_local_game_id().ToUint64();
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.01); callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.01);
for (auto &kv : store_stats_trigger) {
callbacks->addCBResult(kv.second.k_iCallback, &kv.second, sizeof(kv.second));
}
store_stats_trigger.clear();
return true; return true;
} }
@ -999,6 +1026,7 @@ int Steam_User_Stats::GetAchievementIcon( const char *pchName )
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (!pchName) return 0; if (!pchName) return 0;
// callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return 0; return 0;
} }
@ -1068,7 +1096,7 @@ bool Steam_User_Stats::IndicateAchievementProgress( const char *pchName, uint32
if (!pchName) return false; if (!pchName) return false;
if (nCurProgress >= nMaxProgress) return false; if (nCurProgress >= nMaxProgress) return false;
auto ach_name = std::string(pchName); std::string ach_name(pchName);
// find in achievements.json // find in achievements.json
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end(); nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
@ -1103,6 +1131,13 @@ bool Steam_User_Stats::IndicateAchievementProgress( const char *pchName, uint32
save_achievements(); save_achievements();
} catch (...) {} } catch (...) {}
{
UserStatsStored_t data{};
data.m_eResult = EResult::k_EResultOK;
data.m_nGameID = settings->get_local_game_id().ToUint64();
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
UserAchievementStored_t data{}; UserAchievementStored_t data{};
data.m_nGameID = settings->get_local_game_id().ToUint64(); data.m_nGameID = settings->get_local_game_id().ToUint64();
data.m_bGroupAchievement = false; data.m_bGroupAchievement = false;
@ -1110,7 +1145,8 @@ bool Steam_User_Stats::IndicateAchievementProgress( const char *pchName, uint32
data.m_nMaxProgress = nMaxProgress; data.m_nMaxProgress = nMaxProgress;
ach_name.copy(data.m_rgchAchievementName, sizeof(data.m_rgchAchievementName) - 1); ach_name.copy(data.m_rgchAchievementName, sizeof(data.m_rgchAchievementName) - 1);
callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
// callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); // TODO was this correct?
return true; return true;
} }
@ -1153,13 +1189,17 @@ SteamAPICall_t Steam_User_Stats::RequestUserStats( CSteamID steamIDUser )
//if (steamIDUser == settings->get_local_steam_id()) { //if (steamIDUser == settings->get_local_steam_id()) {
// load_achievements(); // load_achievements();
//} //}
UserStatsReceived_t data; UserStatsReceived_t data{};
data.m_nGameID = settings->get_local_game_id().ToUint64(); data.m_nGameID = settings->get_local_game_id().ToUint64();
data.m_eResult = k_EResultOK; data.m_eResult = k_EResultOK;
data.m_steamIDUser = steamIDUser; data.m_steamIDUser = steamIDUser;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // appid 756800 expects both: a callback (global event occurring in the Steam environment),
// and a callresult (the specific result of this function call)
// otherwise it will lock-up and hang at startup
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1);
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
return ret;
} }
@ -1293,7 +1333,9 @@ SteamAPICall_t Steam_User_Stats::FindOrCreateLeaderboard( const char *pchLeaderb
LeaderboardFindResult_t data{}; LeaderboardFindResult_t data{};
data.m_hSteamLeaderboard = 0; data.m_hSteamLeaderboard = 0;
data.m_bLeaderboardFound = 0; data.m_bLeaderboardFound = 0;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
unsigned int board_handle = cache_leaderboard_ifneeded(pchLeaderboardName, eLeaderboardSortMethod, eLeaderboardDisplayType); unsigned int board_handle = cache_leaderboard_ifneeded(pchLeaderboardName, eLeaderboardSortMethod, eLeaderboardDisplayType);
@ -1302,7 +1344,9 @@ SteamAPICall_t Steam_User_Stats::FindOrCreateLeaderboard( const char *pchLeaderb
LeaderboardFindResult_t data{}; LeaderboardFindResult_t data{};
data.m_hSteamLeaderboard = board_handle; data.m_hSteamLeaderboard = board_handle;
data.m_bLeaderboardFound = 1; data.m_bLeaderboardFound = 1;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is the timing ok? auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is the timing ok?
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
return ret;
} }
@ -1317,7 +1361,9 @@ SteamAPICall_t Steam_User_Stats::FindLeaderboard( const char *pchLeaderboardName
LeaderboardFindResult_t data{}; LeaderboardFindResult_t data{};
data.m_hSteamLeaderboard = 0; data.m_hSteamLeaderboard = 0;
data.m_bLeaderboardFound = 0; data.m_bLeaderboardFound = 0;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
std::string name_lower(common_helpers::ascii_to_lowercase(pchLeaderboardName)); std::string name_lower(common_helpers::ascii_to_lowercase(pchLeaderboardName));
@ -1335,7 +1381,9 @@ SteamAPICall_t Steam_User_Stats::FindLeaderboard( const char *pchLeaderboardName
LeaderboardFindResult_t data{}; LeaderboardFindResult_t data{};
data.m_hSteamLeaderboard = find_cached_leaderboard(name_lower); data.m_hSteamLeaderboard = find_cached_leaderboard(name_lower);
data.m_bLeaderboardFound = !!data.m_hSteamLeaderboard; data.m_bLeaderboardFound = !!data.m_hSteamLeaderboard;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
} }
@ -1411,7 +1459,9 @@ SteamAPICall_t Steam_User_Stats::DownloadLeaderboardEntries( SteamLeaderboard_t
data.m_hSteamLeaderboard = hSteamLeaderboard; data.m_hSteamLeaderboard = hSteamLeaderboard;
data.m_hSteamLeaderboardEntries = hSteamLeaderboard; data.m_hSteamLeaderboardEntries = hSteamLeaderboard;
data.m_cEntryCount = entries_count; data.m_cEntryCount = entries_count;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok? auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok?
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
return ret;
} }
// as above, but downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers // as above, but downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers
@ -1451,7 +1501,9 @@ SteamAPICall_t Steam_User_Stats::DownloadLeaderboardEntriesForUsers( SteamLeader
data.m_hSteamLeaderboard = hSteamLeaderboard; data.m_hSteamLeaderboard = hSteamLeaderboard;
data.m_hSteamLeaderboardEntries = hSteamLeaderboard; data.m_hSteamLeaderboardEntries = hSteamLeaderboard;
data.m_cEntryCount = total_count; data.m_cEntryCount = total_count;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok? auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok?
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
return ret;
} }
@ -1568,7 +1620,9 @@ SteamAPICall_t Steam_User_Stats::UploadLeaderboardScore( SteamLeaderboard_t hSte
data.m_bScoreChanged = score_updated; data.m_bScoreChanged = score_updated;
data.m_nGlobalRankNew = new_rank; data.m_nGlobalRankNew = new_rank;
data.m_nGlobalRankPrevious = current_rank; data.m_nGlobalRankPrevious = current_rank;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok? auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok?
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
return ret;
} }
SteamAPICall_t Steam_User_Stats::UploadLeaderboardScore( SteamLeaderboard_t hSteamLeaderboard, int32 nScore, int32 *pScoreDetails, int cScoreDetailsCount ) SteamAPICall_t Steam_User_Stats::UploadLeaderboardScore( SteamLeaderboard_t hSteamLeaderboard, int32 nScore, int32 *pScoreDetails, int cScoreDetailsCount )
@ -1594,7 +1648,9 @@ SteamAPICall_t Steam_User_Stats::AttachLeaderboardUGC( SteamLeaderboard_t hSteam
} }
data.m_hSteamLeaderboard = hSteamLeaderboard; data.m_hSteamLeaderboard = hSteamLeaderboard;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
@ -1613,7 +1669,9 @@ SteamAPICall_t Steam_User_Stats::GetNumberOfCurrentPlayers()
NumberOfCurrentPlayers_t data{}; NumberOfCurrentPlayers_t data{};
data.m_bSuccess = 1; data.m_bSuccess = 1;
data.m_cPlayers = distrib(gen); data.m_cPlayers = distrib(gen);
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
@ -1629,7 +1687,9 @@ SteamAPICall_t Steam_User_Stats::RequestGlobalAchievementPercentages()
GlobalAchievementPercentagesReady_t data{}; GlobalAchievementPercentagesReady_t data{};
data.m_eResult = EResult::k_EResultOK; data.m_eResult = EResult::k_EResultOK;
data.m_nGameID = settings->get_local_game_id().ToUint64(); data.m_nGameID = settings->get_local_game_id().ToUint64();
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }
@ -1724,7 +1784,9 @@ SteamAPICall_t Steam_User_Stats::RequestGlobalStats( int nHistoryDays )
GlobalStatsReceived_t data{}; GlobalStatsReceived_t data{};
data.m_nGameID = settings->get_local_game_id().ToUint64(); data.m_nGameID = settings->get_local_game_id().ToUint64();
data.m_eResult = k_EResultOK; data.m_eResult = k_EResultOK;
return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
return ret;
} }