diff --git a/dep/rcheevos/include/rc_api_editor.h b/dep/rcheevos/include/rc_api_editor.h index 7aab3cb60..61e2fd4ed 100644 --- a/dep/rcheevos/include/rc_api_editor.h +++ b/dep/rcheevos/include/rc_api_editor.h @@ -186,6 +186,37 @@ RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_response(rc_api_update_ RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response); RC_EXPORT void RC_CCONV rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response); +/* --- Update Rich Presence --- */ + +/** + * API parameters for an update rich presence request. + */ +typedef struct rc_api_update_rich_presence_request_t { + /* The username of the developer */ + const char* username; + /* The API token from the login request */ + const char* api_token; + /* The unique identifier of the game */ + uint32_t game_id; + /* The script for the rich_presence */ + const char* script; +} +rc_api_update_rich_presence_request_t; + +/** + * Response data for an update rich presence request. + */ +typedef struct rc_api_update_rich_presence_response_t { + /* Common server-provided response information */ + rc_api_response_t response; +} +rc_api_update_rich_presence_response_t; + +RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params, const rc_api_host_t* host); +RC_EXPORT int RC_CCONV rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response); + /* --- Fetch Badge Range --- */ /** diff --git a/dep/rcheevos/src/rapi/rc_api_editor.c b/dep/rcheevos/src/rapi/rc_api_editor.c index e54771a29..775f73de8 100644 --- a/dep/rcheevos/src/rapi/rc_api_editor.c +++ b/dep/rcheevos/src/rapi/rc_api_editor.c @@ -100,7 +100,7 @@ int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_resp if (!rc_json_get_required_string(&address_str, &response->response, ¬e_fields[0], "Address")) return RC_MISSING_VALUE; - note->address = (unsigned)strtol(address_str, NULL, 16); + note->address = (uint32_t)strtoul(address_str, NULL, 16); if (!rc_json_get_required_string(¬e->note, &response->response, ¬e_fields[2], "Note")) return RC_MISSING_VALUE; @@ -419,6 +419,60 @@ void rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_respon rc_buffer_destroy(&response->response.buffer); } +/* --- Update Rich Presence --- */ + +int rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params) { + return rc_api_init_update_rich_presence_request_hosted(request, api_params, &g_host); +} + +int rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request, + const rc_api_update_rich_presence_request_t* api_params, + const rc_api_host_t* host) { + rc_api_url_builder_t builder; + + rc_api_url_build_dorequest_url(request, host); + + if (api_params->game_id == 0) + return RC_INVALID_STATE; + if (!api_params->script) + return RC_INVALID_STATE; + + rc_url_builder_init(&builder, &request->buffer, 128); + if (!rc_api_url_build_dorequest(&builder, "submitrichpresence", api_params->username, api_params->api_token)) + return builder.result; + + rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); + rc_url_builder_append_str_param(&builder, "d", api_params->script); + + request->post_data = rc_url_builder_finalize(&builder); + request->content_type = RC_CONTENT_TYPE_URLENCODED; + + return builder.result; +} + +int rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response) { + int result; + + rc_json_field_t fields[] = { + RC_JSON_NEW_FIELD("Success"), + RC_JSON_NEW_FIELD("Error"), + RC_JSON_NEW_FIELD("Code"), + }; + + memset(response, 0, sizeof(*response)); + rc_buffer_init(&response->response.buffer); + + result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0])); + if (result != RC_OK || !response->response.succeeded) + return result; + + return RC_OK; +} + +void rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response) { + rc_buffer_destroy(&response->response.buffer); +} + /* --- Fetch Badge Range --- */ int rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params) { diff --git a/dep/rcheevos/src/rcheevos/value.c b/dep/rcheevos/src/rcheevos/value.c index 7987e14d6..082475f35 100644 --- a/dep/rcheevos/src/rcheevos/value.c +++ b/dep/rcheevos/src/rcheevos/value.c @@ -61,27 +61,41 @@ static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_par char buffer[64] = "A:"; const char* buffer_ptr; char* ptr; - char c; + int done; /* convert legacy format into condset */ next_clause = &self->conditions; do { - num_measured_conditions = 0; - /* count the number of joiners and add one to determine the number of clauses. */ + done = 0; num_measured_conditions = 1; buffer_ptr = *memaddr; - while ((c = *buffer_ptr++) && c != '$') { - if (c == '_') { - ++num_measured_conditions; - buffer[0] = 'A'; /* reset to AddSource */ - } - else if (c == '*' && *buffer_ptr == '-') { - /* multiplication by a negative number will convert to SubSource */ - ++buffer_ptr; - buffer[0] = 'B'; + do { + switch (*buffer_ptr++) { + case '_': /* add next */ + ++num_measured_conditions; + buffer[0] = 'A'; /* reset to AddSource */ + break; + + case '*': /* multiply */ + if (*buffer_ptr == '-') { + /* multiplication by a negative number will convert to SubSource */ + ++buffer_ptr; + buffer[0] = 'B'; + } + break; + + case '\0': /* end of string */ + case '$': /* maximum of */ + case ':': /* end of leaderboard clause */ + case ')': /* end of rich presence macro */ + done = 1; + break; + + default: /* assume everything else is valid - bad stuff will be filtered out later */ + break; } - } + } while (!done); /* if last condition is SubSource, we'll need to add a dummy condition for the Measured */ if (buffer[0] == 'B')