Achievements support & inventory customization.
Added achievements support. Achievements are saved like real steam, see your inventory directory.(like items, uses a .json, tool can be used to dump achievements from steam public api). You will need a public apikey. (See https://steamcommunity.com/dev) Reworked item support to split inventory items to defined items.merge-requests/24/head
							parent
							
								
									46f2199cd2
								
							
						
					
					
						commit
						21e08ed220
					
				| 
						 | 
				
			
			@ -1,62 +0,0 @@
 | 
			
		|||
/* Copyright (C) 2019 Nemirtingas (Maxime P)
 | 
			
		||||
   This file is part of the Goldberg Emulator
 | 
			
		||||
 | 
			
		||||
   The Goldberg Emulator is free software; you can redistribute it and/or
 | 
			
		||||
   modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
   License as published by the Free Software Foundation; either
 | 
			
		||||
   version 3 of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
   The Goldberg Emulator is distributed in the hope that it will be useful,
 | 
			
		||||
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
   Lesser General Public License for more details.
 | 
			
		||||
 | 
			
		||||
   You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
   License along with the Goldberg Emulator; if not, see
 | 
			
		||||
   <http://www.gnu.org/licenses/>.  */
 | 
			
		||||
#include "item_db_loader.h"
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include "../json/json.hpp"
 | 
			
		||||
 | 
			
		||||
void read_items_db(std::string items_db, std::map<SteamItemDef_t, std::map<std::string, std::string>> *items, std::atomic_bool *is_loadedb)
 | 
			
		||||
{
 | 
			
		||||
    std::ifstream items_file(items_db);
 | 
			
		||||
    // If there is a file and we opened it
 | 
			
		||||
    if( items_file )
 | 
			
		||||
    {
 | 
			
		||||
        items_file.seekg(0, std::ios::end);
 | 
			
		||||
        size_t size = items_file.tellg();
 | 
			
		||||
        std::string buffer(size, '\0');
 | 
			
		||||
        items_file.seekg(0);
 | 
			
		||||
        // Read it entirely, if the .json file gets too big,
 | 
			
		||||
        // I should look into this and split reads into smaller parts.
 | 
			
		||||
        items_file.read(&buffer[0], size); 
 | 
			
		||||
        items_file.close();
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            std::map<SteamItemDef_t, std::map<std::string, std::string>> tmp;
 | 
			
		||||
            nlohmann::json json = nlohmann::json::parse(buffer);
 | 
			
		||||
 | 
			
		||||
            for (auto& i : json.items())
 | 
			
		||||
            {
 | 
			
		||||
                SteamItemDef_t key = std::stoi((*i).key());
 | 
			
		||||
                nlohmann::json& value = (*i).value();
 | 
			
		||||
                for (auto& j : value.items())
 | 
			
		||||
                {
 | 
			
		||||
                    tmp[key][(*j).key()] = (*j).value();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            items->swap(tmp);
 | 
			
		||||
        }
 | 
			
		||||
        catch (std::exception& e)
 | 
			
		||||
        {
 | 
			
		||||
            PRINT_DEBUG("Error while parsing json: %s\n", e.what());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PRINT_DEBUG("Loaded json. Loaded %u items.\n", items->size());
 | 
			
		||||
    *is_loadedb = true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
/* Copyright (C) 2019 Nemirtingas (Maxime P)
 | 
			
		||||
   This file is part of the Goldberg Emulator
 | 
			
		||||
 | 
			
		||||
   The Goldberg Emulator is free software; you can redistribute it and/or
 | 
			
		||||
   modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
   License as published by the Free Software Foundation; either
 | 
			
		||||
   version 3 of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
   The Goldberg Emulator is distributed in the hope that it will be useful,
 | 
			
		||||
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
   Lesser General Public License for more details.
 | 
			
		||||
 | 
			
		||||
   You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
   License along with the Goldberg Emulator;*/
 | 
			
		||||
#ifndef __ITEM_DB_LOADER_INCLUDED__
 | 
			
		||||
#define __ITEM_DB_LOADER_INCLUDED__
 | 
			
		||||
 | 
			
		||||
#include "base.h" // For SteamItemDef_t
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
void read_items_db(std::string items_db, std::map<SteamItemDef_t, std::map<std::string, std::string>> *items, std::atomic_bool *is_loaded);
 | 
			
		||||
 | 
			
		||||
#endif//__ITEM_DB_LOADER_INCLUDED__
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
#include <fstream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
 | 
			
		||||
struct File_Data {
 | 
			
		||||
    std::string name;
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,11 @@ std::string Local_Storage::get_global_settings_path()
 | 
			
		|||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string Local_Storage::get_global_inventory_path()
 | 
			
		||||
{
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Local_Storage::Local_Storage(std::string save_directory)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -127,6 +133,16 @@ bool Local_Storage::update_save_filenames(std::string folder)
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Local_Storage::load_inventory_file(nlohmann::json& json, std::string const&file)
 | 
			
		||||
{
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Local_Storage::write_inventory_file(nlohmann::json const& json, std::string const&file)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
 | 
			
		||||
{
 | 
			
		||||
    return std::vector<std::string>();
 | 
			
		||||
| 
						 | 
				
			
			@ -378,7 +394,7 @@ std::string Local_Storage::get_program_path()
 | 
			
		|||
 | 
			
		||||
std::string Local_Storage::get_game_settings_path()
 | 
			
		||||
{
 | 
			
		||||
    return get_program_path().append(GAME_SETTINGS_FOLDER).append(PATH_SEPARATOR);
 | 
			
		||||
    return get_program_path().append(game_settings_folder).append(PATH_SEPARATOR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(STEAM_WIN32)
 | 
			
		||||
| 
						 | 
				
			
			@ -508,7 +524,12 @@ std::string Local_Storage::get_path(std::string folder)
 | 
			
		|||
 | 
			
		||||
std::string Local_Storage::get_global_settings_path()
 | 
			
		||||
{
 | 
			
		||||
    return save_directory + SETTINGS_STORAGE_FOLDER + PATH_SEPARATOR;
 | 
			
		||||
    return save_directory + settings_storage_folder + PATH_SEPARATOR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string Local_Storage::get_global_inventory_path()
 | 
			
		||||
{
 | 
			
		||||
    return save_directory + inventory_storage_folder + PATH_SEPARATOR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
 | 
			
		||||
| 
						 | 
				
			
			@ -680,4 +701,54 @@ bool Local_Storage::update_save_filenames(std::string folder)
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Local_Storage::load_inventory_file(nlohmann::json& json, std::string const&file)
 | 
			
		||||
{
 | 
			
		||||
    std::string inv_path = std::move(get_global_inventory_path() + appid + file);
 | 
			
		||||
    std::ifstream inventory_file(inv_path);
 | 
			
		||||
    // If there is a file and we opened it
 | 
			
		||||
    if (inventory_file)
 | 
			
		||||
    {
 | 
			
		||||
        inventory_file.seekg(0, std::ios::end);
 | 
			
		||||
        size_t size = inventory_file.tellg();
 | 
			
		||||
        std::string buffer(size, '\0');
 | 
			
		||||
        inventory_file.seekg(0);
 | 
			
		||||
        // Read it entirely, if the .json file gets too big,
 | 
			
		||||
        // I should look into this and split reads into smaller parts.
 | 
			
		||||
        inventory_file.read(&buffer[0], size);
 | 
			
		||||
        inventory_file.close();
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            json = std::move(nlohmann::json::parse(buffer));
 | 
			
		||||
            PRINT_DEBUG("Loaded inventory \"%s\". Loaded %u items.\n", inv_path.c_str(), json.size());
 | 
			
		||||
            return true;
 | 
			
		||||
        } catch (std::exception& e) {
 | 
			
		||||
            PRINT_DEBUG("Error while parsing \"%s\" inventory json: %s\n", inv_path.c_str(), e.what());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        PRINT_DEBUG("Couldn't open file \"%s\" to read inventory\n", inv_path.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Local_Storage::write_inventory_file(nlohmann::json const& json, std::string const&file)
 | 
			
		||||
{
 | 
			
		||||
    std::string inv_path = std::move(get_global_inventory_path() + appid);
 | 
			
		||||
 | 
			
		||||
    create_directory(inv_path);
 | 
			
		||||
 | 
			
		||||
    std::ofstream inventory_file(inv_path + file, std::ios::trunc | std::ios::out);
 | 
			
		||||
    if (inventory_file)
 | 
			
		||||
    {
 | 
			
		||||
        inventory_file << std::setw(2) << json;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    PRINT_DEBUG("Couldn't open file \"%s\" to write inventory\n", inv_path.c_str());
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,18 +21,21 @@
 | 
			
		|||
#ifndef LOCAL_STORAGE_INCLUDE
 | 
			
		||||
#define LOCAL_STORAGE_INCLUDE
 | 
			
		||||
 | 
			
		||||
#define SETTINGS_STORAGE_FOLDER "settings"
 | 
			
		||||
#define REMOTE_STORAGE_FOLDER "remote"
 | 
			
		||||
#define STATS_STORAGE_FOLDER "stats"
 | 
			
		||||
#define USER_DATA_FOLDER "local"
 | 
			
		||||
 | 
			
		||||
#define GAME_SETTINGS_FOLDER "steam_settings"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "../json/json.hpp"
 | 
			
		||||
 | 
			
		||||
#define MAX_FILENAME_LENGTH 300
 | 
			
		||||
 | 
			
		||||
class Local_Storage {
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr auto inventory_storage_folder = "inventory";
 | 
			
		||||
    static constexpr auto settings_storage_folder  = "settings";
 | 
			
		||||
    static constexpr auto remote_storage_folder    = "remote";
 | 
			
		||||
    static constexpr auto stats_storage_folder     = "stats";
 | 
			
		||||
    static constexpr auto user_data_storage        = "local";
 | 
			
		||||
    static constexpr auto game_settings_folder     = "steam_settings";
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::string save_directory;
 | 
			
		||||
    std::string appid;
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -56,9 +59,13 @@ public:
 | 
			
		|||
    bool file_delete(std::string folder, std::string file);
 | 
			
		||||
    uint64_t file_timestamp(std::string folder, std::string file);
 | 
			
		||||
    std::string get_global_settings_path();
 | 
			
		||||
    std::string get_global_inventory_path();
 | 
			
		||||
    std::string get_path(std::string folder);
 | 
			
		||||
 | 
			
		||||
    bool update_save_filenames(std::string folder);
 | 
			
		||||
 | 
			
		||||
    bool load_inventory_file(nlohmann::json &json, std::string const&file);
 | 
			
		||||
    bool write_inventory_file(nlohmann::json const& json, std::string const&file);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -162,7 +162,7 @@ Steam_Client::Steam_Client()
 | 
			
		|||
    uint64 steam_id = 0;
 | 
			
		||||
    bool generate_new = false;
 | 
			
		||||
    //try to load steam id from game specific settings folder first
 | 
			
		||||
    if (local_storage->get_data(SETTINGS_STORAGE_FOLDER, "user_steam_id.txt", array_steam_id, sizeof(array_steam_id) - 1) > 0) {
 | 
			
		||||
    if (local_storage->get_data(Local_Storage::settings_storage_folder, "user_steam_id.txt", array_steam_id, sizeof(array_steam_id) - 1) > 0) {
 | 
			
		||||
        user_id = CSteamID((uint64)std::atoll(array_steam_id));
 | 
			
		||||
        if (!user_id.IsValid()) {
 | 
			
		||||
            generate_new = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -335,9 +335,6 @@ Steam_Client::Steam_Client()
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string achievements_db_file_path = (Local_Storage::get_game_settings_path() + "achievements.json");
 | 
			
		||||
    std::string items_db_file_path = (Local_Storage::get_game_settings_path() + "items.json");
 | 
			
		||||
 | 
			
		||||
    network = new Networking(settings_server->get_local_steam_id(), appid, port, &custom_broadcasts);
 | 
			
		||||
 | 
			
		||||
    callback_results_client = new SteamCallResults();
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +350,7 @@ Steam_Client::Steam_Client()
 | 
			
		|||
    steam_utils = new Steam_Utils(settings_client, callback_results_client);
 | 
			
		||||
    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_user_stats = new Steam_User_Stats(settings_client, local_storage, callback_results_client, callbacks_client, achievements_db_file_path);
 | 
			
		||||
    steam_user_stats = new Steam_User_Stats(settings_client, local_storage, callback_results_client, callbacks_client);
 | 
			
		||||
    steam_apps = new Steam_Apps(settings_client, callback_results_client);
 | 
			
		||||
    steam_networking = new Steam_Networking(settings_client, network, callbacks_client, run_every_runcb);
 | 
			
		||||
    steam_remote_storage = new Steam_Remote_Storage(settings_client, local_storage, callback_results_client);
 | 
			
		||||
| 
						 | 
				
			
			@ -365,7 +362,7 @@ Steam_Client::Steam_Client()
 | 
			
		|||
    steam_music = new Steam_Music(callbacks_client);
 | 
			
		||||
    steam_musicremote = new Steam_MusicRemote();
 | 
			
		||||
    steam_HTMLsurface = new Steam_HTMLsurface(settings_client, network, callback_results_client, callbacks_client);
 | 
			
		||||
    steam_inventory = new Steam_Inventory(settings_client, callback_results_client, callbacks_client, run_every_runcb, items_db_file_path);
 | 
			
		||||
    steam_inventory = new Steam_Inventory(settings_client, callback_results_client, callbacks_client, run_every_runcb, local_storage);
 | 
			
		||||
    steam_video = new Steam_Video();
 | 
			
		||||
    steam_parental = new Steam_Parental();
 | 
			
		||||
    steam_networking_sockets = new Steam_Networking_Sockets(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
 | 
			
		||||
| 
						 | 
				
			
			@ -383,7 +380,7 @@ Steam_Client::Steam_Client()
 | 
			
		|||
    steam_gameserverstats = new Steam_GameServerStats(settings_server, network, callback_results_server, callbacks_server);
 | 
			
		||||
    steam_gameserver_networking = new Steam_Networking(settings_server, network, callbacks_server, run_every_runcb);
 | 
			
		||||
    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, items_db_file_path);
 | 
			
		||||
    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, callback_results_server, callbacks_server);
 | 
			
		||||
    steam_gameserver_apps = new Steam_Apps(settings_server, callback_results_server);
 | 
			
		||||
    steam_gameserver_networking_sockets = new Steam_Networking_Sockets(settings_server, network, callback_results_server, callbacks_server, run_every_runcb);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,8 +15,8 @@
 | 
			
		|||
   License along with the Goldberg Emulator; if not, see
 | 
			
		||||
   <http://www.gnu.org/licenses/>.  */
 | 
			
		||||
 | 
			
		||||
#include "item_db_loader.h"
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include "base.h" // For SteamItemDef_t
 | 
			
		||||
#include "../json/json.hpp"
 | 
			
		||||
 | 
			
		||||
struct Steam_Inventory_Requests {
 | 
			
		||||
    double timeout = 0.1;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,22 +42,24 @@ class Steam_Inventory :
 | 
			
		|||
    public ISteamInventory002,
 | 
			
		||||
    public ISteamInventory
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr auto items_user_file = "items.json";
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    class Settings *settings;
 | 
			
		||||
    class SteamCallResults *callback_results;
 | 
			
		||||
    class SteamCallBacks *callbacks;
 | 
			
		||||
    class RunEveryRunCB *run_every_runcb;
 | 
			
		||||
    class Local_Storage* local_storage;
 | 
			
		||||
 | 
			
		||||
    std::vector<struct Steam_Inventory_Requests> inventory_requests;
 | 
			
		||||
 | 
			
		||||
    std::map<SteamItemDef_t, std::map<std::string, std::string>> items;
 | 
			
		||||
    // Like typedefs
 | 
			
		||||
    using item_iterator = std::map<SteamItemDef_t, std::map<std::string, std::string>>::iterator;
 | 
			
		||||
    using attr_iterator = std::map<std::string, std::string>::iterator;
 | 
			
		||||
    nlohmann::json defined_items;
 | 
			
		||||
    nlohmann::json user_items;
 | 
			
		||||
 | 
			
		||||
    std::atomic_bool items_loaded;
 | 
			
		||||
    std::string items_db_file;
 | 
			
		||||
    std::once_flag load_items_flag;
 | 
			
		||||
    bool inventory_loaded;
 | 
			
		||||
    bool call_definition_update;
 | 
			
		||||
    bool call_inventory_update;
 | 
			
		||||
    bool definition_update_called;
 | 
			
		||||
    bool full_update_called;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +91,40 @@ struct Steam_Inventory_Requests *get_inventory_result(SteamInventoryResult_t res
 | 
			
		|||
    return &(*request);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void read_items_db()
 | 
			
		||||
{
 | 
			
		||||
    std::string items_db_path = Local_Storage::get_game_settings_path() + items_user_file;
 | 
			
		||||
    PRINT_DEBUG("Items file path: %s\n", items_db_path.c_str());
 | 
			
		||||
    std::ifstream inventory_file(items_db_path);
 | 
			
		||||
    // If there is a file and we opened it
 | 
			
		||||
    if (inventory_file)
 | 
			
		||||
    {
 | 
			
		||||
        inventory_file.seekg(0, std::ios::end);
 | 
			
		||||
        size_t size = inventory_file.tellg();
 | 
			
		||||
        std::string buffer(size, '\0');
 | 
			
		||||
        inventory_file.seekg(0);
 | 
			
		||||
        // Read it entirely, if the .json file gets too big,
 | 
			
		||||
        // I should look into this and split reads into smaller parts.
 | 
			
		||||
        inventory_file.read(&buffer[0], size);
 | 
			
		||||
        inventory_file.close();
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            defined_items = std::move(nlohmann::json::parse(buffer));
 | 
			
		||||
            PRINT_DEBUG("Loaded inventory. Loaded %u items.\n", defined_items.size());
 | 
			
		||||
        }
 | 
			
		||||
        catch (std::exception& e)
 | 
			
		||||
        {
 | 
			
		||||
            PRINT_DEBUG("Error while parsing inventory json: %s\n", e.what());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void read_inventory_db()
 | 
			
		||||
{
 | 
			
		||||
    local_storage->load_inventory_file(user_items, items_user_file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
static void run_every_runcb_cb(void *object)
 | 
			
		||||
| 
						 | 
				
			
			@ -99,21 +135,21 @@ static void run_every_runcb_cb(void *object)
 | 
			
		|||
    obj->RunCallbacks();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Steam_Inventory(class Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb, std::string items_db_file_path)
 | 
			
		||||
Steam_Inventory(class Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb, class Local_Storage *local_storage):
 | 
			
		||||
    settings(settings),
 | 
			
		||||
    callback_results(callback_results),
 | 
			
		||||
    callbacks(callbacks),
 | 
			
		||||
    run_every_runcb(run_every_runcb),
 | 
			
		||||
    local_storage(local_storage),
 | 
			
		||||
    defined_items(nlohmann::json::object()),
 | 
			
		||||
    user_items(nlohmann::json::object()),
 | 
			
		||||
    inventory_loaded(false),
 | 
			
		||||
    call_definition_update(false),
 | 
			
		||||
    call_inventory_update(false),
 | 
			
		||||
    definition_update_called(false),
 | 
			
		||||
    full_update_called(false)
 | 
			
		||||
{
 | 
			
		||||
    items_db_file = items_db_file_path;
 | 
			
		||||
    PRINT_DEBUG("Items file path: %s\n", items_db_file.c_str());
 | 
			
		||||
    items_loaded = false;
 | 
			
		||||
 | 
			
		||||
    this->settings = settings;
 | 
			
		||||
    this->callbacks = callbacks;
 | 
			
		||||
    this->callback_results = callback_results;
 | 
			
		||||
    this->run_every_runcb = run_every_runcb;
 | 
			
		||||
    this->run_every_runcb->add(&Steam_Inventory::run_every_runcb_cb, this);
 | 
			
		||||
 | 
			
		||||
    call_definition_update = false;
 | 
			
		||||
    definition_update_called = false;
 | 
			
		||||
    full_update_called = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
~Steam_Inventory()
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +196,7 @@ bool GetResultItems( SteamInventoryResult_t resultHandle,
 | 
			
		|||
    struct Steam_Inventory_Requests *request = get_inventory_result(resultHandle);
 | 
			
		||||
    if (!request) return false;
 | 
			
		||||
    if (!request->result_done()) return false;
 | 
			
		||||
    if (!inventory_loaded) return false;
 | 
			
		||||
 | 
			
		||||
    if (pOutItemsArray != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -167,21 +204,35 @@ bool GetResultItems( SteamInventoryResult_t resultHandle,
 | 
			
		|||
 | 
			
		||||
        if (request->full_query) {
 | 
			
		||||
            // We end if we reached the end of items or the end of buffer
 | 
			
		||||
            for( auto i = items.begin(); i != items.end() && max_items; ++i, --max_items )
 | 
			
		||||
            for( auto i = user_items.begin(); i != user_items.end() && max_items; ++i, --max_items )
 | 
			
		||||
            {
 | 
			
		||||
                pOutItemsArray->m_iDefinition = i->first;
 | 
			
		||||
                pOutItemsArray->m_itemId = i->first;
 | 
			
		||||
                pOutItemsArray->m_unQuantity = 1;
 | 
			
		||||
                pOutItemsArray->m_iDefinition = std::stoi(i.key());
 | 
			
		||||
                pOutItemsArray->m_itemId = pOutItemsArray->m_iDefinition;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    pOutItemsArray->m_unQuantity = i.value().get<int>();
 | 
			
		||||
                }
 | 
			
		||||
                catch (...)
 | 
			
		||||
                {
 | 
			
		||||
                    pOutItemsArray->m_unQuantity = 0;
 | 
			
		||||
                }
 | 
			
		||||
                pOutItemsArray->m_unFlags = k_ESteamItemNoTrade;
 | 
			
		||||
                ++pOutItemsArray;
 | 
			
		||||
            }
 | 
			
		||||
            *punOutItemsArraySize = std::min(*punOutItemsArraySize, static_cast<uint32>(items.size()));
 | 
			
		||||
            *punOutItemsArraySize = std::min(*punOutItemsArraySize, static_cast<uint32>(user_items.size()));
 | 
			
		||||
        } else {
 | 
			
		||||
            for (auto &itemid : request->instance_ids) {
 | 
			
		||||
                if (!max_items) break;
 | 
			
		||||
                pOutItemsArray->m_iDefinition = itemid;
 | 
			
		||||
                pOutItemsArray->m_itemId = itemid;
 | 
			
		||||
                pOutItemsArray->m_unQuantity = 1;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    pOutItemsArray->m_unQuantity = user_items[itemid].get<int>();
 | 
			
		||||
                }
 | 
			
		||||
                catch (...)
 | 
			
		||||
                {
 | 
			
		||||
                    pOutItemsArray->m_unQuantity = 0;
 | 
			
		||||
                }
 | 
			
		||||
                pOutItemsArray->m_unFlags = k_ESteamItemNoTrade;
 | 
			
		||||
                ++pOutItemsArray;
 | 
			
		||||
                --max_items;
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +241,7 @@ bool GetResultItems( SteamInventoryResult_t resultHandle,
 | 
			
		|||
    }
 | 
			
		||||
    else if (punOutItemsArraySize != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        *punOutItemsArraySize = items.size();
 | 
			
		||||
        *punOutItemsArraySize = user_items.size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PRINT_DEBUG("GetResultItems good\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +329,7 @@ bool GetAllItems( SteamInventoryResult_t *pResultHandle )
 | 
			
		|||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
    struct Steam_Inventory_Requests* request = new_inventory_result();
 | 
			
		||||
 | 
			
		||||
    if (!definition_update_called) call_definition_update = true;
 | 
			
		||||
    call_inventory_update = true;
 | 
			
		||||
 | 
			
		||||
    if (pResultHandle != nullptr)
 | 
			
		||||
        *pResultHandle = request->inventory_result;
 | 
			
		||||
| 
						 | 
				
			
			@ -302,6 +353,7 @@ bool GetItemsByID( SteamInventoryResult_t *pResultHandle, STEAM_ARRAY_COUNT( unC
 | 
			
		|||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
    if (pResultHandle) {
 | 
			
		||||
        struct Steam_Inventory_Requests *request = new_inventory_result(false, pInstanceIDs, unCountInstanceIDs);
 | 
			
		||||
        //call_inventory_update = true;
 | 
			
		||||
        *pResultHandle = request->inventory_result;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -559,15 +611,15 @@ bool GetItemDefinitionIDs(
 | 
			
		|||
 | 
			
		||||
    if (pItemDefIDs == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        *punItemDefIDsArraySize = items.size();
 | 
			
		||||
        *punItemDefIDsArraySize = defined_items.size();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (*punItemDefIDsArraySize < items.size())
 | 
			
		||||
    if (*punItemDefIDsArraySize < defined_items.size())
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    for (auto& i : items)
 | 
			
		||||
        *pItemDefIDs++ = i.first;
 | 
			
		||||
    for (auto i = defined_items.begin(); i != defined_items.end(); ++i)
 | 
			
		||||
        *pItemDefIDs++ = std::stoi(i.key());
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -588,25 +640,38 @@ bool GetItemDefinitionProperty( SteamItemDef_t iDefinition, const char *pchPrope
 | 
			
		|||
    PRINT_DEBUG("GetItemDefinitionProperty %i %s\n", iDefinition, pchPropertyName);
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    item_iterator item;
 | 
			
		||||
    if ((item = items.find(iDefinition)) != items.end())
 | 
			
		||||
    auto item = defined_items.find(std::to_string(iDefinition));
 | 
			
		||||
    if (item != defined_items.end())
 | 
			
		||||
    {
 | 
			
		||||
        attr_iterator attr;
 | 
			
		||||
        if (pchPropertyName != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            // Should I check for punValueBufferSizeOut == nullptr ?
 | 
			
		||||
            // Try to get the property
 | 
			
		||||
            if ((attr = item->second.find(pchPropertyName)) != items[iDefinition].end())
 | 
			
		||||
            auto attr = item.value().find(pchPropertyName);
 | 
			
		||||
            if (attr != item.value().end())
 | 
			
		||||
            {
 | 
			
		||||
                std::string const& val = attr->second;
 | 
			
		||||
                std::string val;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    val = attr.value().get<std::string>();
 | 
			
		||||
                }
 | 
			
		||||
                catch (...)
 | 
			
		||||
                {
 | 
			
		||||
                    pchPropertyName = "";
 | 
			
		||||
                    *punValueBufferSizeOut = 0;
 | 
			
		||||
                    PRINT_DEBUG("Error, item: %d, attr: %s is not a string!", iDefinition, pchPropertyName);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                if (pchValueBuffer != nullptr)
 | 
			
		||||
                {
 | 
			
		||||
                    // copy what we can
 | 
			
		||||
                    strncpy(pchValueBuffer, val.c_str(), *punValueBufferSizeOut);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // Set punValueBufferSizeOut to the property size
 | 
			
		||||
                *punValueBufferSizeOut = std::min(static_cast<uint32>(val.length() + 1), *punValueBufferSizeOut);
 | 
			
		||||
                    *punValueBufferSizeOut = val.length() + 1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (pchValueBuffer != nullptr)
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -628,8 +693,8 @@ bool GetItemDefinitionProperty( SteamItemDef_t iDefinition, const char *pchPrope
 | 
			
		|||
            {
 | 
			
		||||
                // Should I check for punValueBufferSizeOut == nullptr ?
 | 
			
		||||
                *punValueBufferSizeOut = 0;
 | 
			
		||||
                for (auto& i : item->second)
 | 
			
		||||
                    *punValueBufferSizeOut += i.first.length() + 1; // Size of key + comma, and the last is not a comma but null char
 | 
			
		||||
                for (auto i = item.value().begin(); i != item.value().end(); ++i)
 | 
			
		||||
                    *punValueBufferSizeOut += i.key().length() + 1; // Size of key + comma, and the last is not a comma but null char
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -637,16 +702,16 @@ bool GetItemDefinitionProperty( SteamItemDef_t iDefinition, const char *pchPrope
 | 
			
		|||
                uint32_t len = *punValueBufferSizeOut-1;
 | 
			
		||||
                *punValueBufferSizeOut = 0;
 | 
			
		||||
                memset(pchValueBuffer, 0, len);
 | 
			
		||||
                for( auto i = item->second.begin(); i != item->second.end() && len > 0; ++i )
 | 
			
		||||
                for( auto i = item.value().begin(); i != item.value().end() && len > 0; ++i )
 | 
			
		||||
                {
 | 
			
		||||
                    strncat(pchValueBuffer, i->first.c_str(), len);
 | 
			
		||||
                    strncat(pchValueBuffer, i.key().c_str(), len);
 | 
			
		||||
                    // Count how many chars we copied
 | 
			
		||||
                    // Either the string length or the buffer size if its too small
 | 
			
		||||
                    uint32 x = std::min(len, static_cast<uint32>(i->first.length()));
 | 
			
		||||
                    uint32 x = std::min(len, static_cast<uint32>(i.key().length()));
 | 
			
		||||
                    *punValueBufferSizeOut += x;
 | 
			
		||||
                    len -= x;
 | 
			
		||||
 | 
			
		||||
                    if (len && std::distance(i, item->second.end()) != 1) // If this is not the last item, add a comma
 | 
			
		||||
                    if (len && std::distance(i, item.value().end()) != 1) // If this is not the last item, add a comma
 | 
			
		||||
                        strncat(pchValueBuffer, ",", len--);
 | 
			
		||||
 | 
			
		||||
                    // Always add 1, its a comma or the null terminator
 | 
			
		||||
| 
						 | 
				
			
			@ -781,23 +846,25 @@ bool SubmitUpdateProperties( SteamInventoryUpdateHandle_t handle, SteamInventory
 | 
			
		|||
 | 
			
		||||
void RunCallbacks()
 | 
			
		||||
{
 | 
			
		||||
    if (call_definition_update || inventory_requests.size()) {
 | 
			
		||||
        std::call_once(load_items_flag, [&]() {
 | 
			
		||||
            std::thread items_load_thread(read_items_db, items_db_file, &items, &items_loaded);
 | 
			
		||||
            items_load_thread.detach();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (items_loaded) {
 | 
			
		||||
    if (call_definition_update) {
 | 
			
		||||
        read_items_db();
 | 
			
		||||
        definition_update_called = true;
 | 
			
		||||
 | 
			
		||||
        SteamInventoryDefinitionUpdate_t data = {};
 | 
			
		||||
        callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
 | 
			
		||||
        call_definition_update = false;
 | 
			
		||||
            definition_update_called = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
 | 
			
		||||
    if (call_inventory_update) {
 | 
			
		||||
        read_inventory_db();
 | 
			
		||||
        inventory_loaded = true;
 | 
			
		||||
 | 
			
		||||
        call_inventory_update = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (definition_update_called && inventory_loaded)
 | 
			
		||||
    {
 | 
			
		||||
        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
 | 
			
		||||
        for (auto& r : inventory_requests) {
 | 
			
		||||
            if (!r.done && std::chrono::duration_cast<std::chrono::duration<double>>(now - r.time_created).count() > r.timeout) {
 | 
			
		||||
                if (r.full_query) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ Steam_Remote_Storage(class Settings *settings, Local_Storage *local_storage, cla
 | 
			
		|||
    this->local_storage = local_storage;
 | 
			
		||||
    this->callback_results = callback_results;
 | 
			
		||||
    steam_cloud_enabled = true;
 | 
			
		||||
    local_storage->update_save_filenames(REMOTE_STORAGE_FOLDER);
 | 
			
		||||
    local_storage->update_save_filenames(Local_Storage::remote_storage_folder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NOTE
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ bool	FileWrite( const char *pchFile, const void *pvData, int32 cubData )
 | 
			
		|||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::FileWrite %s %u\n", pchFile, cubData);
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
    int data_stored = local_storage->store_data(REMOTE_STORAGE_FOLDER, pchFile, (char* )pvData, cubData);
 | 
			
		||||
    int data_stored = local_storage->store_data(Local_Storage::remote_storage_folder, pchFile, (char* )pvData, cubData);
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::Stored %i, %u\n", data_stored, data_stored == cubData);
 | 
			
		||||
    return data_stored == cubData;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ int32	FileRead( const char *pchFile, void *pvData, int32 cubDataToRead )
 | 
			
		|||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::FileRead %s %i\n", pchFile, cubDataToRead);
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
    int read_data = local_storage->get_data(REMOTE_STORAGE_FOLDER, pchFile, (char* )pvData, cubDataToRead);
 | 
			
		||||
    int read_data = local_storage->get_data(Local_Storage::remote_storage_folder, pchFile, (char* )pvData, cubDataToRead);
 | 
			
		||||
    if (read_data < 0) read_data = 0;
 | 
			
		||||
    PRINT_DEBUG("Read %i\n", read_data);
 | 
			
		||||
    return read_data;
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ SteamAPICall_t FileWriteAsync( const char *pchFile, const void *pvData, uint32 c
 | 
			
		|||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::FileWriteAsync\n");
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
    bool success = local_storage->store_data(REMOTE_STORAGE_FOLDER, pchFile, (char* )pvData, cubData) == cubData;
 | 
			
		||||
    bool success = local_storage->store_data(Local_Storage::remote_storage_folder, pchFile, (char* )pvData, cubData) == cubData;
 | 
			
		||||
    RemoteStorageFileWriteAsyncComplete_t data;
 | 
			
		||||
    data.m_eResult = k_EResultOK;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ SteamAPICall_t FileReadAsync( const char *pchFile, uint32 nOffset, uint32 cubToR
 | 
			
		|||
    PRINT_DEBUG("Steam_Remote_Storage::FileReadAsync\n");
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    unsigned int size = local_storage->file_size(REMOTE_STORAGE_FOLDER, pchFile);
 | 
			
		||||
    unsigned int size = local_storage->file_size(Local_Storage::remote_storage_folder, pchFile);
 | 
			
		||||
 | 
			
		||||
    RemoteStorageFileReadAsyncComplete_t data;
 | 
			
		||||
    if (size <= nOffset) {
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ bool	FileReadAsyncComplete( SteamAPICall_t hReadCall, void *pvBuffer, uint32 cub
 | 
			
		|||
        return false;
 | 
			
		||||
 | 
			
		||||
    char *temp = new char[a_read->size];
 | 
			
		||||
    int read_data = local_storage->get_data(REMOTE_STORAGE_FOLDER, a_read->file_name, (char* )temp, a_read->size);
 | 
			
		||||
    int read_data = local_storage->get_data(Local_Storage::remote_storage_folder, a_read->file_name, (char* )temp, a_read->size);
 | 
			
		||||
    if (read_data < a_read->to_read + a_read->offset) {
 | 
			
		||||
        delete[] temp;
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -175,7 +175,7 @@ bool	FileForget( const char *pchFile )
 | 
			
		|||
bool	FileDelete( const char *pchFile )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::FileDelete\n");
 | 
			
		||||
    return local_storage->file_delete(REMOTE_STORAGE_FOLDER, pchFile);
 | 
			
		||||
    return local_storage->file_delete(Local_Storage::remote_storage_folder, pchFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
STEAM_CALL_RESULT( RemoteStorageFileShareResult_t )
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +184,7 @@ SteamAPICall_t FileShare( const char *pchFile )
 | 
			
		|||
    PRINT_DEBUG("Steam_Remote_Storage::FileShare\n");
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
    RemoteStorageFileShareResult_t data = {};
 | 
			
		||||
    if (local_storage->file_exists(REMOTE_STORAGE_FOLDER, pchFile)) {
 | 
			
		||||
    if (local_storage->file_exists(Local_Storage::remote_storage_folder, pchFile)) {
 | 
			
		||||
        data.m_eResult = k_EResultOK;
 | 
			
		||||
        data.m_hFile = generate_steam_api_call_id();
 | 
			
		||||
        strncpy(data.m_rgchFilename, pchFile, sizeof(data.m_rgchFilename) - 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -237,7 +237,7 @@ bool FileWriteStreamClose( UGCFileWriteStreamHandle_t writeHandle )
 | 
			
		|||
    if (stream_writes.end() == request)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    local_storage->store_data(REMOTE_STORAGE_FOLDER, request->file_name, request->file_data.data(), request->file_data.size());
 | 
			
		||||
    local_storage->store_data(Local_Storage::remote_storage_folder, request->file_name, request->file_data.data(), request->file_data.size());
 | 
			
		||||
    stream_writes.erase(request);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -258,25 +258,25 @@ bool FileWriteStreamCancel( UGCFileWriteStreamHandle_t writeHandle )
 | 
			
		|||
bool	FileExists( const char *pchFile )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::FileExists %s\n", pchFile);
 | 
			
		||||
    return local_storage->file_exists(REMOTE_STORAGE_FOLDER, pchFile);
 | 
			
		||||
    return local_storage->file_exists(Local_Storage::remote_storage_folder, pchFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool	FilePersisted( const char *pchFile )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::FilePersisted\n");
 | 
			
		||||
    return local_storage->file_exists(REMOTE_STORAGE_FOLDER, pchFile);
 | 
			
		||||
    return local_storage->file_exists(Local_Storage::remote_storage_folder, pchFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32	GetFileSize( const char *pchFile )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::GetFileSize %s\n", pchFile);
 | 
			
		||||
    return local_storage->file_size(REMOTE_STORAGE_FOLDER, pchFile);
 | 
			
		||||
    return local_storage->file_size(Local_Storage::remote_storage_folder, pchFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64	GetFileTimestamp( const char *pchFile )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::GetFileTimestamp\n");
 | 
			
		||||
    return local_storage->file_timestamp(REMOTE_STORAGE_FOLDER, pchFile);
 | 
			
		||||
    return local_storage->file_timestamp(Local_Storage::remote_storage_folder, pchFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ERemoteStoragePlatform GetSyncPlatforms( const char *pchFile )
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +290,7 @@ ERemoteStoragePlatform GetSyncPlatforms( const char *pchFile )
 | 
			
		|||
int32 GetFileCount()
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::GetFileCount\n");
 | 
			
		||||
    int32 num = local_storage->count_files(REMOTE_STORAGE_FOLDER);
 | 
			
		||||
    int32 num = local_storage->count_files(Local_Storage::remote_storage_folder);
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::File count: %i\n", num);
 | 
			
		||||
    return num;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +299,7 @@ const char *GetFileNameAndSize( int iFile, int32 *pnFileSizeInBytes )
 | 
			
		|||
{
 | 
			
		||||
    PRINT_DEBUG("Steam_Remote_Storage::GetFileNameAndSize %i\n", iFile);
 | 
			
		||||
    static char output_filename[MAX_FILENAME_LENGTH];
 | 
			
		||||
    if (local_storage->iterate_file(REMOTE_STORAGE_FOLDER, iFile, output_filename, pnFileSizeInBytes)) {
 | 
			
		||||
    if (local_storage->iterate_file(Local_Storage::remote_storage_folder, iFile, output_filename, pnFileSizeInBytes)) {
 | 
			
		||||
        PRINT_DEBUG("Steam_Remote_Storage::Name: |%s|, size: %i\n", output_filename, pnFileSizeInBytes ? *pnFileSizeInBytes : 0);
 | 
			
		||||
        return output_filename;
 | 
			
		||||
    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +372,7 @@ SteamAPICall_t UGCDownload( UGCHandle_t hContent, uint32 unPriority )
 | 
			
		|||
        data.m_eResult = k_EResultOK;
 | 
			
		||||
        data.m_hFile = hContent;
 | 
			
		||||
        data.m_nAppID = settings->get_local_game_id().AppID();
 | 
			
		||||
        data.m_nSizeInBytes = local_storage->file_size(REMOTE_STORAGE_FOLDER, shared_files[hContent]);
 | 
			
		||||
        data.m_nSizeInBytes = local_storage->file_size(Local_Storage::remote_storage_folder, shared_files[hContent]);
 | 
			
		||||
        shared_files[hContent].copy(data.m_pchFileName, sizeof(data.m_pchFileName) - 1);
 | 
			
		||||
        data.m_ulSteamIDOwner = settings->get_local_steam_id().ConvertToUint64();
 | 
			
		||||
        downloaded_files[hContent].file = shared_files[hContent];
 | 
			
		||||
| 
						 | 
				
			
			@ -426,7 +426,7 @@ int32	UGCRead( UGCHandle_t hContent, void *pvData, int32 cubDataToRead, uint32 c
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    Downloaded_File f = downloaded_files[hContent];
 | 
			
		||||
    int read_data = local_storage->get_data(REMOTE_STORAGE_FOLDER, f.file, (char* )pvData, cubDataToRead, cOffset);
 | 
			
		||||
    int read_data = local_storage->get_data(Local_Storage::remote_storage_folder, f.file, (char* )pvData, cubDataToRead, cOffset);
 | 
			
		||||
 | 
			
		||||
    if (eAction == k_EUGCRead_Close || (eAction == k_EUGCRead_ContinueReadingUntilFinished && (read_data < cubDataToRead || (cOffset + cubDataToRead) >= f.total_size))) {
 | 
			
		||||
        downloaded_files.erase(hContent);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,7 +149,7 @@ bool GetUserDataFolder( char *pchBuffer, int cubBuffer )
 | 
			
		|||
    PRINT_DEBUG("GetUserDataFolder\n");
 | 
			
		||||
    if (!cubBuffer) return false;
 | 
			
		||||
 | 
			
		||||
    std::string user_data = local_storage->get_path(USER_DATA_FOLDER);
 | 
			
		||||
    std::string user_data = local_storage->get_path(Local_Storage::user_data_storage);
 | 
			
		||||
    strncpy(pchBuffer, user_data.c_str(), cubBuffer - 1);
 | 
			
		||||
    pchBuffer[cubBuffer - 1] = 0;
 | 
			
		||||
    return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,14 +38,19 @@ public ISteamUserStats009,
 | 
			
		|||
public ISteamUserStats010,
 | 
			
		||||
public ISteamUserStats
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr auto achievements_user_file = "achievements.json";
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    Local_Storage *local_storage;
 | 
			
		||||
    Settings *settings;
 | 
			
		||||
    SteamCallResults *callback_results;
 | 
			
		||||
    class SteamCallBacks *callbacks;
 | 
			
		||||
    std::vector<struct Steam_Leaderboard> leaderboards;
 | 
			
		||||
 | 
			
		||||
    std::string db_file_path;
 | 
			
		||||
    nlohmann::json achievements;
 | 
			
		||||
    nlohmann::json defined_achievements;
 | 
			
		||||
    nlohmann::json user_achievements;
 | 
			
		||||
 | 
			
		||||
unsigned int find_leaderboard(std::string name)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -58,9 +63,10 @@ unsigned int find_leaderboard(std::string name)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void load_achievements()
 | 
			
		||||
void load_achievements_db()
 | 
			
		||||
{
 | 
			
		||||
    std::ifstream achs_file(db_file_path);
 | 
			
		||||
    std::string file_path = Local_Storage::get_game_settings_path() + achievements_user_file;
 | 
			
		||||
    std::ifstream achs_file(file_path);
 | 
			
		||||
 | 
			
		||||
    if (achs_file)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -73,26 +79,34 @@ void load_achievements()
 | 
			
		|||
        achs_file.read(&buffer[0], size);
 | 
			
		||||
        achs_file.close();
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            achievements = nlohmann::json::parse(buffer);
 | 
			
		||||
        try {
 | 
			
		||||
            defined_achievements = std::move(nlohmann::json::parse(buffer));
 | 
			
		||||
        } catch (std::exception &e) {
 | 
			
		||||
            PRINT_DEBUG("Error while parsing json: \"%s\" : %s\n", file_path.c_str(), e.what());
 | 
			
		||||
        }
 | 
			
		||||
        catch (std::exception &e)
 | 
			
		||||
        {
 | 
			
		||||
            PRINT_DEBUG("(Achievements): Error while parsing json: %s\n", e.what());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        PRINT_DEBUG("Couldn't open file \"%s\" to read achievements definition\n", file_path.c_str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void load_achievements()
 | 
			
		||||
{
 | 
			
		||||
    local_storage->load_inventory_file(user_achievements, achievements_user_file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
Steam_User_Stats(Settings *settings, Local_Storage *local_storage, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, std::string const&achievements_db_file_path):
 | 
			
		||||
Steam_User_Stats(Settings *settings, Local_Storage *local_storage, class SteamCallResults *callback_results, class SteamCallBacks *callbacks):
 | 
			
		||||
    settings(settings),
 | 
			
		||||
    local_storage(local_storage),
 | 
			
		||||
    callback_results(callback_results),
 | 
			
		||||
    callbacks(callbacks),
 | 
			
		||||
    db_file_path(achievements_db_file_path)
 | 
			
		||||
    defined_achievements(nlohmann::json::object()),
 | 
			
		||||
    user_achievements(nlohmann::json::object())
 | 
			
		||||
{
 | 
			
		||||
    load_achievements();
 | 
			
		||||
    load_achievements_db(); // achievements db
 | 
			
		||||
    load_achievements(); // achievements per user
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ask the server to send down this user's data and achievements for this game
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +132,7 @@ bool GetStat( const char *pchName, int32 *pData )
 | 
			
		|||
    if (!pchName || !pData) return false;
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    int read_data = local_storage->get_data(STATS_STORAGE_FOLDER, pchName, (char* )pData, sizeof(*pData));
 | 
			
		||||
    int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, pchName, (char* )pData, sizeof(*pData));
 | 
			
		||||
    if (read_data == sizeof(int32))
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +145,7 @@ bool GetStat( const char *pchName, float *pData )
 | 
			
		|||
    if (!pchName || !pData) return false;
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    int read_data = local_storage->get_data(STATS_STORAGE_FOLDER, pchName, (char* )pData, sizeof(*pData));
 | 
			
		||||
    int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, pchName, (char* )pData, sizeof(*pData));
 | 
			
		||||
    if (read_data == sizeof(int32))
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +160,7 @@ bool SetStat( const char *pchName, int32 nData )
 | 
			
		|||
    if (!pchName) return false;
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    return local_storage->store_data(STATS_STORAGE_FOLDER, pchName, (char* )&nData, sizeof(nData)) == sizeof(nData);
 | 
			
		||||
    return local_storage->store_data(Local_Storage::stats_storage_folder, pchName, (char* )&nData, sizeof(nData)) == sizeof(nData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SetStat( const char *pchName, float fData )
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +169,7 @@ bool SetStat( const char *pchName, float fData )
 | 
			
		|||
    if (!pchName) return false;
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    return local_storage->store_data(STATS_STORAGE_FOLDER, pchName, (char* )&fData, sizeof(fData)) == sizeof(fData);
 | 
			
		||||
    return local_storage->store_data(Local_Storage::stats_storage_folder, pchName, (char* )&fData, sizeof(fData)) == sizeof(fData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool UpdateAvgRateStat( const char *pchName, float flCountThisSession, double dSessionLength )
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +178,7 @@ bool UpdateAvgRateStat( const char *pchName, float flCountThisSession, double dS
 | 
			
		|||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    char data[sizeof(float) + sizeof(float) + sizeof(double)];
 | 
			
		||||
    int read_data = local_storage->get_data(STATS_STORAGE_FOLDER, pchName, (char* )data, sizeof(*data));
 | 
			
		||||
    int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, pchName, (char* )data, sizeof(*data));
 | 
			
		||||
    float oldcount = 0;
 | 
			
		||||
    double oldsessionlength = 0;
 | 
			
		||||
    if (read_data == sizeof(data)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -180,30 +194,28 @@ bool UpdateAvgRateStat( const char *pchName, float flCountThisSession, double dS
 | 
			
		|||
    memcpy(data + sizeof(float), &oldcount, sizeof(oldcount));
 | 
			
		||||
    memcpy(data + sizeof(float) * 2, &oldsessionlength, sizeof(oldsessionlength));
 | 
			
		||||
 | 
			
		||||
    return local_storage->store_data(STATS_STORAGE_FOLDER, pchName, data, sizeof(data)) == sizeof(data);
 | 
			
		||||
    return local_storage->store_data(Local_Storage::stats_storage_folder, pchName, data, sizeof(data)) == sizeof(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Achievement flag accessors
 | 
			
		||||
bool GetAchievement( const char *pchName, bool *pbAchieved )
 | 
			
		||||
{
 | 
			
		||||
    //TODO: these achievement functions need to load a list of achievements from somewhere, return false so that kf2 doesn't loop endlessly
 | 
			
		||||
    PRINT_DEBUG("GetAchievement %s\n", pchName);
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        auto it = std::find_if(achievements.begin(), achievements.end(), [pchName]( nlohmann::json &item ) {
 | 
			
		||||
            return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName]( nlohmann::json &item ) {
 | 
			
		||||
            return item["name"].get<std::string>() == pchName;
 | 
			
		||||
        });
 | 
			
		||||
        if (it != achievements.end())
 | 
			
		||||
        {
 | 
			
		||||
            *pbAchieved = it.value()["earned"];
 | 
			
		||||
        auto ach = user_achievements.find(pchName);
 | 
			
		||||
        if (it != defined_achievements.end() && ach != user_achievements.end()) {
 | 
			
		||||
            if(pbAchieved != nullptr) *pbAchieved = (*ach)["earned"];
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch (...)
 | 
			
		||||
    {
 | 
			
		||||
    } catch (...) {}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    if (pbAchieved != nullptr)* pbAchieved = false;
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -211,21 +223,18 @@ bool GetAchievement( const char *pchName, bool *pbAchieved )
 | 
			
		|||
bool SetAchievement( const char *pchName )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("SetAchievement %s\n", pchName);
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        auto it = std::find_if(achievements.begin(), achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
            return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
            return item["name"].get<std::string>() == pchName;
 | 
			
		||||
        });
 | 
			
		||||
        if (it != achievements.end())
 | 
			
		||||
        {
 | 
			
		||||
            it.value()["earned"] = 1;
 | 
			
		||||
        if (it != defined_achievements.end()) {
 | 
			
		||||
            user_achievements[pchName]["earned"] = true;
 | 
			
		||||
            user_achievements[pchName]["earned_time"] = static_cast<uint32>(std::time(nullptr));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch (...)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    } catch (...) {}
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -233,20 +242,18 @@ bool SetAchievement( const char *pchName )
 | 
			
		|||
bool ClearAchievement( const char *pchName )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("ClearAchievement %s\n", pchName);
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        auto it = std::find_if(achievements.begin(), achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
            return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
        });
 | 
			
		||||
        if (it != achievements.end())
 | 
			
		||||
        {
 | 
			
		||||
            it.value()["earned"] = 0;
 | 
			
		||||
        if (it != defined_achievements.end()) {
 | 
			
		||||
            user_achievements[pchName]["earned"] = false;
 | 
			
		||||
            user_achievements[pchName]["earned_time"] = static_cast<uint32>(0);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch (...)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    } catch (...) {}
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -258,26 +265,22 @@ bool ClearAchievement( const char *pchName )
 | 
			
		|||
bool GetAchievementAndUnlockTime( const char *pchName, bool *pbAchieved, uint32 *punUnlockTime )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetAchievementAndUnlockTime\n");
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        auto it = std::find_if(achievements.begin(), achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
            return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
        });
 | 
			
		||||
        if (it != achievements.end())
 | 
			
		||||
        {
 | 
			
		||||
            *pbAchieved = it.value()["earned"].get<int>();
 | 
			
		||||
            *punUnlockTime = std::time(NULL);
 | 
			
		||||
            //*punUnlockTime = it.value()["time_earned"].get<uint32>();
 | 
			
		||||
        auto ach = user_achievements.find(pchName);
 | 
			
		||||
        if (it != defined_achievements.end() && ach != user_achievements.end()) {
 | 
			
		||||
            if(pbAchieved != nullptr) *pbAchieved = (*ach)["earned"];
 | 
			
		||||
            if(punUnlockTime != nullptr) *punUnlockTime = (*ach)["earned_time"];
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch (...)
 | 
			
		||||
    {
 | 
			
		||||
    } catch (...) {}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *pbAchieved = false;
 | 
			
		||||
    *punUnlockTime = 0;
 | 
			
		||||
    if(pbAchieved != nullptr) *pbAchieved = false;
 | 
			
		||||
    if(punUnlockTime != nullptr) *punUnlockTime = 0;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -294,11 +297,7 @@ bool StoreStats()
 | 
			
		|||
    PRINT_DEBUG("StoreStats\n");
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    std::ofstream achiev_file(db_file_path, std::ios::trunc | std::ios::out);
 | 
			
		||||
    if (achiev_file)
 | 
			
		||||
    {
 | 
			
		||||
        achiev_file << std::setw(2) << achievements;
 | 
			
		||||
    }
 | 
			
		||||
    local_storage->write_inventory_file(user_achievements, achievements_user_file);
 | 
			
		||||
 | 
			
		||||
    UserStatsStored_t data;
 | 
			
		||||
    data.m_nGameID = settings->get_local_game_id().ToUint64();
 | 
			
		||||
| 
						 | 
				
			
			@ -317,6 +316,8 @@ bool StoreStats()
 | 
			
		|||
int GetAchievementIcon( const char *pchName )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetAchievementIcon\n");
 | 
			
		||||
    if (pchName == nullptr) return 0;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -327,56 +328,40 @@ int GetAchievementIcon( const char *pchName )
 | 
			
		|||
const char * GetAchievementDisplayAttribute( const char *pchName, const char *pchKey )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetAchievementDisplayAttribute %s %s\n", pchName, pchKey);
 | 
			
		||||
    if (pchName == nullptr) return "";
 | 
			
		||||
    if (pchKey == nullptr) return "";
 | 
			
		||||
 | 
			
		||||
    if (strcmp (pchKey, "name") == 0) {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            auto it = std::find_if(achievements.begin(), achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
        try {
 | 
			
		||||
            auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
                return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
            });
 | 
			
		||||
            if (it != achievements.end())
 | 
			
		||||
            {
 | 
			
		||||
            if (it != defined_achievements.end()) {
 | 
			
		||||
                return it.value()["displayName"].get<std::string>().c_str();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (...)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        } catch (...) {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (strcmp (pchKey, "desc") == 0) {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            auto it = std::find_if(achievements.begin(), achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
        try {
 | 
			
		||||
            auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
                return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
            });
 | 
			
		||||
            if (it != achievements.end())
 | 
			
		||||
            {
 | 
			
		||||
            if (it != defined_achievements.end()) {
 | 
			
		||||
                return it.value()["description"].get<std::string>().c_str();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (...)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        } catch (...) {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (strcmp (pchKey, "hidden") == 0) {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            auto it = std::find_if(achievements.begin(), achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
        try {
 | 
			
		||||
            auto it = std::find_if(defined_achievements.begin(), defined_achievements.end(), [pchName](nlohmann::json& item) {
 | 
			
		||||
                return static_cast<std::string const&>(item["name"]) == pchName;
 | 
			
		||||
            });
 | 
			
		||||
            if (it != achievements.end())
 | 
			
		||||
            {
 | 
			
		||||
                return (it.value()["hidden"].get<int>() ? "1" : "0");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (...)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            if (it != defined_achievements.end()) {
 | 
			
		||||
                return it.value()["description"].get<std::string>().c_str();
 | 
			
		||||
            }
 | 
			
		||||
        } catch (...) {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return "";
 | 
			
		||||
| 
						 | 
				
			
			@ -388,6 +373,8 @@ const char * GetAchievementDisplayAttribute( const char *pchName, const char *pc
 | 
			
		|||
bool IndicateAchievementProgress( const char *pchName, uint32 nCurProgress, uint32 nMaxProgress )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("IndicateAchievementProgress\n");
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -396,21 +383,16 @@ bool IndicateAchievementProgress( const char *pchName, uint32 nCurProgress, uint
 | 
			
		|||
uint32 GetNumAchievements()
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetNumAchievements\n");
 | 
			
		||||
    return achievements.size();
 | 
			
		||||
    return defined_achievements.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get achievement name iAchievement in [0,GetNumAchievements)
 | 
			
		||||
const char * GetAchievementName( uint32 iAchievement )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetAchievementName\n");
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        return static_cast<std::string const&>(achievements[iAchievement]["name"]).c_str();
 | 
			
		||||
    }
 | 
			
		||||
    catch (...)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
        return defined_achievements[iAchievement]["name"].get<std::string>().c_str();
 | 
			
		||||
    } catch (...) {}
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -428,7 +410,10 @@ SteamAPICall_t RequestUserStats( CSteamID steamIDUser )
 | 
			
		|||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    // Enable this to allow hot reload achievements status
 | 
			
		||||
    //if (steamIDUser == settings->get_local_steam_id()) {
 | 
			
		||||
    //    load_achievements();
 | 
			
		||||
    //}
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    UserStatsReceived_t data;
 | 
			
		||||
    data.m_nGameID = settings->get_local_game_id().ToUint64();
 | 
			
		||||
| 
						 | 
				
			
			@ -442,6 +427,8 @@ SteamAPICall_t RequestUserStats( CSteamID steamIDUser )
 | 
			
		|||
bool GetUserStat( CSteamID steamIDUser, const char *pchName, int32 *pData )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetUserStat %s %llu\n", pchName, steamIDUser.ConvertToUint64());
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    if (steamIDUser == settings->get_local_steam_id()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -456,6 +443,8 @@ bool GetUserStat( CSteamID steamIDUser, const char *pchName, int32 *pData )
 | 
			
		|||
bool GetUserStat( CSteamID steamIDUser, const char *pchName, float *pData )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetUserStat %s %llu\n", pchName, steamIDUser.ConvertToUint64());
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    std::lock_guard<std::recursive_mutex> lock(global_mutex);
 | 
			
		||||
 | 
			
		||||
    if (steamIDUser == settings->get_local_steam_id()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -470,6 +459,12 @@ bool GetUserStat( CSteamID steamIDUser, const char *pchName, float *pData )
 | 
			
		|||
bool GetUserAchievement( CSteamID steamIDUser, const char *pchName, bool *pbAchieved )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetUserAchievement %s\n", pchName);
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    if (steamIDUser == settings->get_local_steam_id()) {
 | 
			
		||||
        return GetAchievement(pchName, pbAchieved);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -477,6 +472,11 @@ bool GetUserAchievement( CSteamID steamIDUser, const char *pchName, bool *pbAchi
 | 
			
		|||
bool GetUserAchievementAndUnlockTime( CSteamID steamIDUser, const char *pchName, bool *pbAchieved, uint32 *punUnlockTime )
 | 
			
		||||
{
 | 
			
		||||
    PRINT_DEBUG("GetUserAchievementAndUnlockTime %s\n", pchName);
 | 
			
		||||
    if (pchName == nullptr) return false;
 | 
			
		||||
 | 
			
		||||
    if (steamIDUser == settings->get_local_steam_id()) {
 | 
			
		||||
        return GetAchievementAndUnlockTime(pchName, pbAchieved, punUnlockTime);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -486,6 +486,13 @@ bool ResetAllStats( bool bAchievementsToo )
 | 
			
		|||
{
 | 
			
		||||
    PRINT_DEBUG("ResetAllStats\n");
 | 
			
		||||
    //TODO
 | 
			
		||||
    if (bAchievementsToo) {
 | 
			
		||||
        std::for_each(user_achievements.begin(), user_achievements.end(), [](nlohmann::json& v) {
 | 
			
		||||
            v["earned"] = false;
 | 
			
		||||
            v["earned_time"] = 0;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue