diff --git a/dep/rcheevos/include/rc_api_info.h b/dep/rcheevos/include/rc_api_info.h index c4a33d372..ee5121df0 100644 --- a/dep/rcheevos/include/rc_api_info.h +++ b/dep/rcheevos/include/rc_api_info.h @@ -239,7 +239,10 @@ RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_titles_response(rc_api_fetch_g * API parameters for a fetch games list request. */ typedef struct rc_api_fetch_hash_library_request_t { - /* The unique identifier of the console to query */ + /** + * The unique identifier of the console to query. + * Passing RC_CONSOLE_UNKNOWN will return hashes for all consoles. + */ uint32_t console_id; } rc_api_fetch_hash_library_request_t; diff --git a/dep/rcheevos/include/rc_api_user.h b/dep/rcheevos/include/rc_api_user.h index cf1876e54..c977da956 100644 --- a/dep/rcheevos/include/rc_api_user.h +++ b/dep/rcheevos/include/rc_api_user.h @@ -216,19 +216,19 @@ RC_EXPORT void RC_CCONV rc_api_destroy_fetch_followed_users_response(rc_api_fetc /* --- Fetch All Progress --- */ /** - * API parameters for a fetch all progress request. + * API parameters for a fetch all user progress request. */ -typedef struct rc_api_fetch_all_progress_request_t { +typedef struct rc_api_fetch_all_user_progress_request_t { /* The username of the player */ const char* username; /* The API token from the login request */ const char* api_token; /* The unique identifier of the console to query */ uint32_t console_id; -} rc_api_fetch_all_progress_request_t; +} rc_api_fetch_all_user_progress_request_t; -/* An all-progress entry */ -typedef struct rc_api_all_progress_entry_t { +/* An all-user-progress entry */ +typedef struct rc_api_all_user_progress_entry_t { /* The unique identifier of the game */ uint32_t game_id; /* The total number of achievements for this game */ @@ -237,25 +237,25 @@ typedef struct rc_api_all_progress_entry_t { uint32_t num_unlocked_achievements; /* The total number of unlocked achievements for this game in hardcore mode */ uint32_t num_unlocked_achievements_hardcore; -} rc_api_all_progress_entry_t; +} rc_api_all_user_progress_entry_t; /** - * Response data for a fetch all progress request. + * Response data for a fetch all user progress request. */ -typedef struct rc_api_fetch_all_progress_response_t { +typedef struct rc_api_fetch_all_user_progress_response_t { /* An array of entries, one per game */ - rc_api_all_progress_entry_t* entries; + rc_api_all_user_progress_entry_t* entries; /* The number of items in the entries array */ uint32_t num_entries; /* Common server-provided response information */ rc_api_response_t response; -} rc_api_fetch_all_progress_response_t; +} rc_api_fetch_all_user_progress_response_t; -RC_EXPORT int RC_CCONV rc_api_init_fetch_all_progress_request(rc_api_request_t* request, const rc_api_fetch_all_progress_request_t* api_params); -RC_EXPORT int RC_CCONV rc_api_init_fetch_all_progress_request_hosted(rc_api_request_t* request, const rc_api_fetch_all_progress_request_t* api_params, const rc_api_host_t* host); -RC_EXPORT int RC_CCONV rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_response_t* response, const rc_api_server_response_t* server_response); -RC_EXPORT void RC_CCONV rc_api_destroy_fetch_all_progress_response(rc_api_fetch_all_progress_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_all_user_progress_request(rc_api_request_t* request, const rc_api_fetch_all_user_progress_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_init_fetch_all_user_progress_request_hosted(rc_api_request_t* request, const rc_api_fetch_all_user_progress_request_t* api_params, const rc_api_host_t* host); +RC_EXPORT int RC_CCONV rc_api_process_fetch_all_user_progress_server_response(rc_api_fetch_all_user_progress_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_all_user_progress_response(rc_api_fetch_all_user_progress_response_t* response); RC_END_C_DECLS diff --git a/dep/rcheevos/include/rc_client.h b/dep/rcheevos/include/rc_client.h index 5e7b37561..b09fd3264 100644 --- a/dep/rcheevos/include/rc_client.h +++ b/dep/rcheevos/include/rc_client.h @@ -323,7 +323,7 @@ typedef struct rc_client_subset_t { RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id); /*****************************************************************************\ -| Game Info | +| Fetch Game Hashes | \*****************************************************************************/ typedef struct rc_client_hash_library_entry_t @@ -357,13 +357,16 @@ typedef void(RC_CCONV* rc_client_fetch_hash_library_callback_t)(int result, cons RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_hash_library( rc_client_t* client, uint32_t console_id, rc_client_fetch_hash_library_callback_t callback, void* callback_userdata); - /** * Destroys a previously-allocated result from the rc_client_destroy_hash_library() callback. */ RC_EXPORT void RC_CCONV rc_client_destroy_hash_library(rc_client_hash_library_t* list); -typedef struct rc_client_all_progress_list_entry_t +/*****************************************************************************\ +| Game Info | +\*****************************************************************************/ + +typedef struct rc_client_all_user_progress_entry_t { /* The unique identifier of the game */ uint32_t game_id; @@ -373,21 +376,21 @@ typedef struct rc_client_all_progress_list_entry_t uint32_t num_unlocked_achievements; /* The total number of unlocked achievements for this game in hardcore mode */ uint32_t num_unlocked_achievements_hardcore; -} rc_client_all_progress_list_entry_t; +} rc_client_all_user_progress_entry_t; -typedef struct rc_client_all_progress_list_t +typedef struct rc_client_all_user_progress_t { /* An array of entries, one per game */ - rc_client_all_progress_list_entry_t* entries; + rc_client_all_user_progress_entry_t* entries; /* The number of items in the entries array */ uint32_t num_entries; -} rc_client_all_progress_list_t; +} rc_client_all_user_progress_t; /** * Callback that is fired when an all progress query completes. list may be null if the query failed. */ -typedef void(RC_CCONV* rc_client_fetch_all_progress_list_callback_t)(int result, const char* error_message, - rc_client_all_progress_list_t* list, +typedef void(RC_CCONV* rc_client_fetch_all_user_progress_callback_t)(int result, const char* error_message, + rc_client_all_user_progress_t* list, rc_client_t* client, void* callback_userdata); /** @@ -396,13 +399,13 @@ typedef void(RC_CCONV* rc_client_fetch_all_progress_list_callback_t)(int result, * the user's achievement unlock count for both softcore and hardcore modes. */ RC_EXPORT rc_client_async_handle_t* RC_CCONV -rc_client_begin_fetch_all_progress_list(rc_client_t* client, uint32_t console_id, - rc_client_fetch_all_progress_list_callback_t callback, void* callback_userdata); +rc_client_begin_fetch_all_user_progress(rc_client_t* client, uint32_t console_id, + rc_client_fetch_all_user_progress_callback_t callback, void* callback_userdata); /** * Destroys a previously-allocated result from the rc_client_begin_fetch_all_progress_list() callback. */ -RC_EXPORT void RC_CCONV rc_client_destroy_all_progress_list(rc_client_all_progress_list_t* list); +RC_EXPORT void RC_CCONV rc_client_destroy_all_user_progress(rc_client_all_user_progress_t* list); /*****************************************************************************\ | Achievements | diff --git a/dep/rcheevos/src/rapi/rc_api_info.c b/dep/rcheevos/src/rapi/rc_api_info.c index 4874bc1e7..eb28c4d75 100644 --- a/dep/rcheevos/src/rapi/rc_api_info.c +++ b/dep/rcheevos/src/rapi/rc_api_info.c @@ -2,7 +2,6 @@ #include "rc_api_common.h" #include "rc_api_runtime.h" -#include "rc_consoles.h" #include "rc_runtime_types.h" #include "../rc_compat.h" @@ -509,9 +508,7 @@ int rc_api_init_fetch_hash_library_request_hosted(rc_api_request_t* request, rc_api_url_builder_t builder; rc_api_url_build_dorequest_url(request, host); - if (api_params->console_id == RC_CONSOLE_UNKNOWN) - return RC_INVALID_STATE; - + /* note: unauthenticated request */ rc_url_builder_init(&builder, &request->buffer, 48); rc_url_builder_append_str_param(&builder, "r", "hashlibrary"); rc_url_builder_append_unum_param(&builder, "c", api_params->console_id); @@ -529,7 +526,6 @@ int rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_ rc_json_iterator_t iterator; rc_json_field_t field; int result; - char* end; rc_json_field_t fields[] = { RC_JSON_NEW_FIELD("Success"), @@ -545,36 +541,36 @@ int rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_ if (result != RC_OK) return result; - if (!fields[2].value_start) - { + if (!fields[2].value_start) { /* call rc_json_get_required_object to generate the error message */ rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "MD5List"); return RC_MISSING_VALUE; } response->num_entries = fields[2].array_size; - rc_buffer_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_hash_library_entry_t))); + if (response->num_entries > 0) { + rc_buffer_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_hash_library_entry_t))); - response->entries = (rc_api_hash_library_entry_t*)rc_buffer_alloc( - &response->response.buffer, response->num_entries * sizeof(rc_api_hash_library_entry_t)); - if (!response->entries) - return RC_OUT_OF_MEMORY; + response->entries = (rc_api_hash_library_entry_t*)rc_buffer_alloc( + &response->response.buffer, response->num_entries * sizeof(rc_api_hash_library_entry_t)); + if (!response->entries) + return RC_OUT_OF_MEMORY; - memset(&iterator, 0, sizeof(iterator)); - iterator.json = fields[2].value_start; - iterator.end = fields[2].value_end; + memset(&iterator, 0, sizeof(iterator)); + iterator.json = fields[2].value_start; + iterator.end = fields[2].value_end; - entry = response->entries; - while (rc_json_get_next_object_field(&iterator, &field)) - { - /* TODO: This isn't handling escape characters in the key, the RC JSON parsing functions have no method for it. */ - entry->hash = rc_buffer_strncpy(&response->response.buffer, field.name, field.name_len); + entry = response->entries; + while (rc_json_get_next_object_field(&iterator, &field)) { + /* TODO: This isn't handling escape characters in the key, the RC JSON parsing functions have no method for it. */ + entry->hash = rc_buffer_strncpy(&response->response.buffer, field.name, field.name_len); - field.name = ""; - if (!rc_json_get_unum(&entry->game_id, &field, "")) - return RC_MISSING_VALUE; + field.name = ""; + if (!rc_json_get_unum(&entry->game_id, &field, "")) + return RC_MISSING_VALUE; - ++entry; + ++entry; + } } return RC_OK; diff --git a/dep/rcheevos/src/rapi/rc_api_user.c b/dep/rcheevos/src/rapi/rc_api_user.c index 8c18bccf4..323756cfd 100644 --- a/dep/rcheevos/src/rapi/rc_api_user.c +++ b/dep/rcheevos/src/rapi/rc_api_user.c @@ -376,15 +376,15 @@ void rc_api_destroy_fetch_followed_users_response(rc_api_fetch_followed_users_re /* --- Fetch All Progress --- */ -int rc_api_init_fetch_all_progress_request(rc_api_request_t* request, - const rc_api_fetch_all_progress_request_t* api_params) +int rc_api_init_fetch_all_user_progress_request(rc_api_request_t* request, + const rc_api_fetch_all_user_progress_request_t* api_params) { - return rc_api_init_fetch_all_progress_request_hosted(request, api_params, &g_host); + return rc_api_init_fetch_all_user_progress_request_hosted(request, api_params, &g_host); } -int rc_api_init_fetch_all_progress_request_hosted(rc_api_request_t* request, - const rc_api_fetch_all_progress_request_t* api_params, - const rc_api_host_t* host) +int rc_api_init_fetch_all_user_progress_request_hosted(rc_api_request_t* request, + const rc_api_fetch_all_user_progress_request_t* api_params, + const rc_api_host_t* host) { rc_api_url_builder_t builder; @@ -404,14 +404,11 @@ int rc_api_init_fetch_all_progress_request_hosted(rc_api_request_t* request, return builder.result; } -int rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_response_t* response, - const rc_api_server_response_t* server_response) +int rc_api_process_fetch_all_user_progress_server_response(rc_api_fetch_all_user_progress_response_t* response, + const rc_api_server_response_t* server_response) { - rc_api_all_progress_entry_t* entry; - rc_json_iterator_t iterator; - rc_json_field_t field; + rc_api_all_user_progress_entry_t* entry; int result; - char* end; rc_json_field_t fields[] = { RC_JSON_NEW_FIELD("Success"), @@ -430,51 +427,57 @@ int rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_ result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); - if (result != RC_OK) + if (result != RC_OK || !response->response.succeeded) return result; - if (!fields[2].value_start) - { + if (!fields[2].value_start) { /* call rc_json_get_required_object to generate the error message */ rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "Response"); return RC_MISSING_VALUE; } response->num_entries = fields[2].array_size; - rc_buffer_reserve(&response->response.buffer, response->num_entries * sizeof(rc_api_all_progress_entry_t)); - response->entries = (rc_api_all_progress_entry_t*)rc_buffer_alloc( - &response->response.buffer, response->num_entries * sizeof(rc_api_all_progress_entry_t)); - if (!response->entries) - return RC_OUT_OF_MEMORY; + if (response->num_entries > 0) { + rc_json_iterator_t iterator; + rc_json_field_t field; + char* end; - memset(&iterator, 0, sizeof(iterator)); - iterator.json = fields[2].value_start; - iterator.end = fields[2].value_end; + rc_buffer_reserve(&response->response.buffer, response->num_entries * sizeof(rc_api_all_user_progress_entry_t)); - entry = response->entries; - while (rc_json_get_next_object_field(&iterator, &field)) - { - entry->game_id = strtol(field.name, &end, 10); + response->entries = (rc_api_all_user_progress_entry_t*)rc_buffer_alloc( + &response->response.buffer, response->num_entries * sizeof(rc_api_all_user_progress_entry_t)); + if (!response->entries) + return RC_OUT_OF_MEMORY; - field.name = ""; - if (!rc_json_get_required_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), response, &field, - "")) + memset(&iterator, 0, sizeof(iterator)); + iterator.json = fields[2].value_start; + iterator.end = fields[2].value_end; + + entry = response->entries; + while (rc_json_get_next_object_field(&iterator, &field)) { - return RC_MISSING_VALUE; + entry->game_id = strtol(field.name, &end, 10); + + field.name = ""; + if (!rc_json_get_required_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), + &response->response, &field, "")) + { + return RC_MISSING_VALUE; + } + + rc_json_get_optional_unum(&entry->num_achievements, &entry_fields[0], "Achievements", 0); + rc_json_get_optional_unum(&entry->num_unlocked_achievements, &entry_fields[1], "Unlocked", 0); + rc_json_get_optional_unum(&entry->num_unlocked_achievements_hardcore, &entry_fields[2], "UnlockedHardcore", 0); + + ++entry; } - - rc_json_get_optional_unum(&entry->num_achievements, &entry_fields[0], "Achievements", 0); - rc_json_get_optional_unum(&entry->num_unlocked_achievements, &entry_fields[1], "Unlocked", 0); - rc_json_get_optional_unum(&entry->num_unlocked_achievements_hardcore, &entry_fields[2], "UnlockedHardcore", 0); - - ++entry; } return RC_OK; } -void rc_api_destroy_fetch_all_progress_response(rc_api_fetch_all_progress_response_t* response) +void rc_api_destroy_fetch_all_user_progress_response(rc_api_fetch_all_user_progress_response_t* response) { rc_buffer_destroy(&response->response.buffer); } diff --git a/dep/rcheevos/src/rc_client.c b/dep/rcheevos/src/rc_client.c index 80758f50d..5c758c677 100644 --- a/dep/rcheevos/src/rc_client.c +++ b/dep/rcheevos/src/rc_client.c @@ -3247,7 +3247,7 @@ static void rc_client_fetch_hash_library_callback(const rc_api_server_response_t else { rc_client_hash_library_t* list; - const size_t list_size = sizeof(*list) + sizeof(rc_client_leaderboard_entry_t) * hashlib_response.num_entries; + const size_t list_size = sizeof(*list) + sizeof(rc_client_hash_library_entry_t) * hashlib_response.num_entries; size_t needed_size = list_size; uint32_t i; @@ -3339,21 +3339,24 @@ void rc_client_destroy_hash_library(rc_client_hash_library_t* list) free(list); } -typedef struct rc_client_fetch_all_progress_callback_data_t +/* ===== Fetch Game Hashes ===== */ + +typedef struct rc_client_fetch_all_user_progress_callback_data_t { rc_client_t* client; - rc_client_fetch_all_progress_list_callback_t callback; + rc_client_fetch_all_user_progress_callback_t callback; void* callback_userdata; uint32_t console_id; rc_client_async_handle_t async_handle; -} rc_client_fetch_all_progress_callback_data_t; +} rc_client_fetch_all_user_progress_callback_data_t; -static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t* server_response, void* callback_data) +static void rc_client_fetch_all_user_progress_callback(const rc_api_server_response_t* server_response, + void* callback_data) { - rc_client_fetch_all_progress_callback_data_t* ap_callback_data = - (rc_client_fetch_all_progress_callback_data_t*)callback_data; + rc_client_fetch_all_user_progress_callback_data_t* ap_callback_data = + (rc_client_fetch_all_user_progress_callback_data_t*)callback_data; rc_client_t* client = ap_callback_data->client; - rc_api_fetch_all_progress_response_t ap_response; + rc_api_fetch_all_user_progress_response_t ap_response; const char* error_message; int result; @@ -3367,7 +3370,7 @@ static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t return; } - result = rc_api_process_fetch_all_progress_server_response(&ap_response, server_response); + result = rc_api_process_fetch_all_user_progress_server_response(&ap_response, server_response); error_message = rc_client_server_error_message(&result, server_response->http_status_code, &ap_response.response); if (error_message) { @@ -3377,10 +3380,10 @@ static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t } else { - rc_client_all_progress_list_t* list; - const size_t list_size = sizeof(*list) + sizeof(rc_client_all_progress_list_entry_t) * ap_response.num_entries; + rc_client_all_user_progress_t* list; + const size_t list_size = sizeof(*list) + sizeof(rc_client_all_user_progress_entry_t) * ap_response.num_entries; - list = (rc_client_all_progress_list_t*)malloc(list_size); + list = (rc_client_all_user_progress_t*)malloc(list_size); if (!list) { ap_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, @@ -3388,10 +3391,10 @@ static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t } else { - rc_client_all_progress_list_entry_t* entry = list->entries = - (rc_client_all_progress_list_entry_t*)((uint8_t*)list + sizeof(*list)); - const rc_api_all_progress_entry_t* hlentry = ap_response.entries; - const rc_api_all_progress_entry_t* stop = hlentry + ap_response.num_entries; + rc_client_all_user_progress_entry_t* entry = list->entries = + (rc_client_all_user_progress_entry_t*)((uint8_t*)list + sizeof(*list)); + const rc_api_all_user_progress_entry_t* hlentry = ap_response.entries; + const rc_api_all_user_progress_entry_t* stop = hlentry + ap_response.num_entries; for (; hlentry < stop; ++hlentry, ++entry) { @@ -3407,16 +3410,16 @@ static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t } } - rc_api_destroy_fetch_all_progress_response(&ap_response); + rc_api_destroy_fetch_all_user_progress_response(&ap_response); free(ap_callback_data); } -rc_client_async_handle_t* rc_client_begin_fetch_all_progress_list(rc_client_t* client, uint32_t console_id, - rc_client_fetch_all_progress_list_callback_t callback, +rc_client_async_handle_t* rc_client_begin_fetch_all_user_progress(rc_client_t* client, uint32_t console_id, + rc_client_fetch_all_user_progress_callback_t callback, void* callback_userdata) { - rc_api_fetch_all_progress_request_t api_params; - rc_client_fetch_all_progress_callback_data_t* callback_data; + rc_api_fetch_all_user_progress_request_t api_params; + rc_client_fetch_all_user_progress_callback_data_t* callback_data; rc_client_async_handle_t* async_handle; rc_api_request_t request; int result; @@ -3437,7 +3440,7 @@ rc_client_async_handle_t* rc_client_begin_fetch_all_progress_list(rc_client_t* c api_params.api_token = client->user.token; api_params.console_id = console_id; - result = rc_api_init_fetch_all_progress_request_hosted(&request, &api_params, &client->state.host); + result = rc_api_init_fetch_all_user_progress_request_hosted(&request, &api_params, &client->state.host); if (result != RC_OK) { @@ -3446,7 +3449,7 @@ rc_client_async_handle_t* rc_client_begin_fetch_all_progress_list(rc_client_t* c return NULL; } - callback_data = (rc_client_fetch_all_progress_callback_data_t*)calloc(1, sizeof(*callback_data)); + callback_data = (rc_client_fetch_all_user_progress_callback_data_t*)calloc(1, sizeof(*callback_data)); if (!callback_data) { callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata); @@ -3460,13 +3463,13 @@ rc_client_async_handle_t* rc_client_begin_fetch_all_progress_list(rc_client_t* c async_handle = &callback_data->async_handle; rc_client_begin_async(client, async_handle); - client->callbacks.server_call(&request, rc_client_fetch_all_progress_callback, callback_data, client); + client->callbacks.server_call(&request, rc_client_fetch_all_user_progress_callback, callback_data, client); rc_api_destroy_request(&request); return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL; } -void rc_client_destroy_all_progress_list(rc_client_all_progress_list_t* list) +void rc_client_destroy_all_user_progress(rc_client_all_user_progress_t* list) { free(list); } diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 708dd5bea..02be58551 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -218,14 +218,14 @@ static void CancelHashDatabaseRequests(); static void FetchHashLibraryCallback(int result, const char* error_message, rc_client_hash_library_t* list, rc_client_t* client, void* callback_userdata); -static void FetchAllProgressCallback(int result, const char* error_message, rc_client_all_progress_list_t* list, +static void FetchAllProgressCallback(int result, const char* error_message, rc_client_all_user_progress_t* list, rc_client_t* client, void* callback_userdata); -static void BuildHashDatabase(const rc_client_hash_library_t* hashlib, const rc_client_all_progress_list_t* allprog); +static void BuildHashDatabase(const rc_client_hash_library_t* hashlib, const rc_client_all_user_progress_t* allprog); static bool SortAndSaveHashDatabase(Error* error); static FileSystem::ManagedCFilePtr OpenProgressDatabase(bool for_write, bool truncate, Error* error); -static void BuildProgressDatabase(const rc_client_all_progress_list_t* allprog); +static void BuildProgressDatabase(const rc_client_all_user_progress_t* allprog); static void UpdateProgressDatabase(bool force); static void ClearProgressDatabase(); @@ -295,7 +295,7 @@ struct State rc_client_async_handle_t* fetch_hash_library_request = nullptr; rc_client_hash_library_t* fetch_hash_library_result = nullptr; rc_client_async_handle_t* fetch_all_progress_request = nullptr; - rc_client_all_progress_list_t* fetch_all_progress_result = nullptr; + rc_client_all_user_progress_t* fetch_all_progress_result = nullptr; #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION rc_client_async_handle_t* load_raintegration_request = nullptr; @@ -1588,7 +1588,7 @@ void Achievements::HandleSubsetCompleteEvent(const rc_client_event_t* event) INFO_LOG("Subset {} ({}) complete", event->subset->title, event->subset->id); UpdateGameSummary(false, false); - if (g_settings.achievements_notifications && event->subset->badge_name) + if (g_settings.achievements_notifications && event->subset->badge_name[0] != '\0') { // Need to grab the icon for the subset. std::string badge_path = GetLocalImagePath(event->subset->badge_name, RC_IMAGE_TYPE_GAME); @@ -3960,7 +3960,7 @@ void Achievements::BeginRefreshHashDatabase() s_state.fetch_hash_library_request = rc_client_begin_fetch_hash_library(s_state.client, RC_CONSOLE_PLAYSTATION, FetchHashLibraryCallback, nullptr); s_state.fetch_all_progress_request = - rc_client_begin_fetch_all_progress_list(s_state.client, RC_CONSOLE_PLAYSTATION, FetchAllProgressCallback, nullptr); + rc_client_begin_fetch_all_user_progress(s_state.client, RC_CONSOLE_PLAYSTATION, FetchAllProgressCallback, nullptr); if (!s_state.fetch_hash_library_request || !s_state.fetch_hash_library_request) { ERROR_LOG("Failed to create hash database refresh requests."); @@ -3984,7 +3984,7 @@ void Achievements::FetchHashLibraryCallback(int result, const char* error_messag FinishRefreshHashDatabase(); } -void Achievements::FetchAllProgressCallback(int result, const char* error_message, rc_client_all_progress_list_t* list, +void Achievements::FetchAllProgressCallback(int result, const char* error_message, rc_client_all_user_progress_t* list, rc_client_t* client, void* callback_userdata) { s_state.fetch_all_progress_request = nullptr; @@ -4004,7 +4004,7 @@ void Achievements::CancelHashDatabaseRequests() { if (s_state.fetch_all_progress_result) { - rc_client_destroy_all_progress_list(s_state.fetch_all_progress_result); + rc_client_destroy_all_user_progress(s_state.fetch_all_progress_result); s_state.fetch_all_progress_result = nullptr; } if (s_state.fetch_all_progress_request) @@ -4040,7 +4040,7 @@ void Achievements::FinishRefreshHashDatabase() BuildProgressDatabase(s_state.fetch_all_progress_result); // tidy up - rc_client_destroy_all_progress_list(s_state.fetch_all_progress_result); + rc_client_destroy_all_user_progress(s_state.fetch_all_progress_result); s_state.fetch_all_progress_result = nullptr; rc_client_destroy_hash_library(s_state.fetch_hash_library_result); s_state.fetch_hash_library_result = nullptr; @@ -4050,7 +4050,7 @@ void Achievements::FinishRefreshHashDatabase() } void Achievements::BuildHashDatabase(const rc_client_hash_library_t* hashlib, - const rc_client_all_progress_list_t* allprog) + const rc_client_all_user_progress_t* allprog) { std::vector dbentries; dbentries.reserve(hashlib->num_entries); @@ -4079,8 +4079,8 @@ void Achievements::BuildHashDatabase(const rc_client_hash_library_t* hashlib, } // fill in achievement counts - for (const rc_client_all_progress_list_entry_t& entry : - std::span(allprog->entries, allprog->num_entries)) + for (const rc_client_all_user_progress_entry_t& entry : + std::span(allprog->entries, allprog->num_entries)) { // can have multiple hashes with the same game id, update count on all of them bool found_one = false; @@ -4108,6 +4108,11 @@ void Achievements::BuildHashDatabase(const rc_client_hash_library_t* hashlib, bool Achievements::CreateHashDatabaseFromSeedDatabase(const std::string& path, Error* error) { std::optional yaml_data = Host::ReadResourceFileToString("achievement_hashlib.yaml", false, error); + if (!yaml_data.has_value()) + { + Error::SetStringView(error, "Seed database is missing."); + return false; + } const ryml::Tree yaml = ryml::parse_in_place(to_csubstr(path), c4::substr(reinterpret_cast(yaml_data->data()), yaml_data->size())); @@ -4374,7 +4379,7 @@ FileSystem::ManagedCFilePtr Achievements::OpenProgressDatabase(bool for_write, b return nullptr; } -void Achievements::BuildProgressDatabase(const rc_client_all_progress_list_t* allprog) +void Achievements::BuildProgressDatabase(const rc_client_all_user_progress_t* allprog) { // no point storing it in memory, just write directly to the file Error error; @@ -4401,8 +4406,8 @@ void Achievements::BuildProgressDatabase(const rc_client_all_progress_list_t* al writer.WriteU32(games_with_unlocks); if (games_with_unlocks > 0) { - for (const rc_client_all_progress_list_entry_t& entry : - std::span(allprog->entries, allprog->num_entries)) + for (const rc_client_all_user_progress_entry_t& entry : + std::span(allprog->entries, allprog->num_entries)) { if ((entry.num_unlocked_achievements + entry.num_unlocked_achievements_hardcore) == 0) continue;