dep/rcheevos: Bump to 74860c9

This commit is contained in:
Stenzek
2024-01-13 14:24:04 +10:00
parent ecbd693d22
commit e2e85a06cd
42 changed files with 1126 additions and 505 deletions

View File

@ -475,13 +475,13 @@ int rc_json_get_required_array(uint32_t* num_entries, rc_json_field_t* array_fie
return 0;
#endif
if (!rc_json_get_optional_array(num_entries, array_field, response, field, field_name))
if (!rc_json_get_optional_array(num_entries, array_field, field, field_name))
return rc_json_missing_field(response, field);
return 1;
}
int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* array_field, const rc_json_field_t* field, const char* field_name) {
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
return 0;
@ -783,6 +783,52 @@ int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const
return rc_json_missing_field(response, field);
}
int rc_json_get_float(float* out, const rc_json_field_t* field, const char* field_name) {
int32_t whole, fraction, fraction_denominator;
const char* decimal = field->value_start;
if (!decimal) {
*out = 0.0f;
return 0;
}
if (!rc_json_get_num(&whole, field, field_name))
return 0;
while (decimal < field->value_end && *decimal != '.')
++decimal;
fraction = 0;
fraction_denominator = 1;
if (decimal) {
++decimal;
while (decimal < field->value_end && *decimal >= '0' && *decimal <= '9') {
fraction *= 10;
fraction += *decimal - '0';
fraction_denominator *= 10;
++decimal;
}
}
if (whole < 0)
fraction = -fraction;
*out = (float)whole + ((float)fraction / (float)fraction_denominator);
return 1;
}
void rc_json_get_optional_float(float* out, const rc_json_field_t* field, const char* field_name, float default_value) {
if (!rc_json_get_float(out, field, field_name))
*out = default_value;
}
int rc_json_get_required_float(float* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
if (rc_json_get_float(out, field, field_name))
return 1;
return rc_json_missing_field(response, field);
}
int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name) {
struct tm tm;

View File

@ -6,9 +6,7 @@
#include <stddef.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
RC_BEGIN_C_DECLS
#define RC_CONTENT_TYPE_URLENCODED "application/x-www-form-urlencoded"
@ -47,16 +45,19 @@ int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_serv
int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_field_t* field, const char* field_name);
int rc_json_get_num(int32_t* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_float(float* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name);
void rc_json_get_optional_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name, const char* default_value);
void rc_json_get_optional_num(int32_t* out, const rc_json_field_t* field, const char* field_name, int default_value);
void rc_json_get_optional_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name, uint32_t default_value);
void rc_json_get_optional_float(float* out, const rc_json_field_t* field, const char* field_name, float default_value);
void rc_json_get_optional_bool(int* out, const rc_json_field_t* field, const char* field_name, int default_value);
int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* iterator, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* iterator, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_num(int32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_float(float* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name);
@ -74,8 +75,6 @@ void rc_url_builder_append_str_param(rc_api_url_builder_t* builder, const char*
void rc_api_url_build_dorequest_url(rc_api_request_t* request);
int rc_api_url_build_dorequest(rc_api_url_builder_t* builder, const char* api, const char* username, const char* api_token);
#ifdef __cplusplus
}
#endif
RC_END_C_DECLS
#endif /* RC_API_COMMON_H */

View File

@ -1,5 +1,6 @@
#include "rc_api_editor.h"
#include "rc_api_common.h"
#include "rc_api_runtime.h"
#include "../rc_compat.h"
#include "../rhash/md5.h"
@ -185,6 +186,15 @@ void rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t
/* --- Update Achievement --- */
static const char* rc_type_string(uint32_t type) {
switch (type) {
case RC_ACHIEVEMENT_TYPE_MISSABLE: return "missable";
case RC_ACHIEVEMENT_TYPE_PROGRESSION: return "progression";
case RC_ACHIEVEMENT_TYPE_WIN: return "win_condition";
default: return "";
}
}
int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params) {
rc_api_url_builder_t builder;
char buffer[33];
@ -216,6 +226,7 @@ int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_a
rc_url_builder_append_unum_param(&builder, "f", api_params->category);
if (api_params->badge)
rc_url_builder_append_str_param(&builder, "b", api_params->badge);
rc_url_builder_append_str_param(&builder, "x", rc_type_string(api_params->type));
/* Evaluate the signature. */
md5_init(&md5);

View File

@ -92,6 +92,20 @@ int rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* r
return rc_api_process_fetch_game_data_server_response(response, &response_obj);
}
static int rc_parse_achievement_type(const char* type)
{
if (strcmp(type, "missable") == 0)
return RC_ACHIEVEMENT_TYPE_MISSABLE;
if (strcmp(type, "win_condition") == 0)
return RC_ACHIEVEMENT_TYPE_WIN;
if (strcmp(type, "progression") == 0)
return RC_ACHIEVEMENT_TYPE_PROGRESSION;
return RC_ACHIEVEMENT_TYPE_STANDARD;
}
int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_response_t* response, const rc_api_server_response_t* server_response) {
rc_api_achievement_definition_t* achievement;
rc_api_leaderboard_definition_t* leaderboard;
@ -120,10 +134,6 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
RC_JSON_NEW_FIELD("RichPresencePatch"),
RC_JSON_NEW_FIELD("Achievements"), /* array */
RC_JSON_NEW_FIELD("Leaderboards") /* array */
/* unused fields
RC_JSON_NEW_FIELD("ForumTopicID"),
RC_JSON_NEW_FIELD("Flags")
* unused fields */
};
rc_json_field_t achievement_fields[] = {
@ -136,7 +146,10 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
RC_JSON_NEW_FIELD("Author"),
RC_JSON_NEW_FIELD("BadgeName"),
RC_JSON_NEW_FIELD("Created"),
RC_JSON_NEW_FIELD("Modified")
RC_JSON_NEW_FIELD("Modified"),
RC_JSON_NEW_FIELD("Type"),
RC_JSON_NEW_FIELD("Rarity"),
RC_JSON_NEW_FIELD("RarityHardcore")
};
rc_json_field_t leaderboard_fields[] = {
@ -247,6 +260,35 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon
return RC_MISSING_VALUE;
achievement->updated = (time_t)timet;
achievement->type = RC_ACHIEVEMENT_TYPE_STANDARD;
if (achievement_fields[10].value_end) {
len = achievement_fields[10].value_end - achievement_fields[10].value_start - 2;
if (len < sizeof(format) - 1) {
memcpy(format, achievement_fields[10].value_start + 1, len);
format[len] = '\0';
achievement->type = rc_parse_achievement_type(format);
}
}
/* legacy support : if title contains[m], change type to missable and remove[m] from title */
if (memcmp(achievement->title, "[m]", 3) == 0) {
len = 3;
while (achievement->title[len] == ' ')
++len;
achievement->title += len;
achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE;
}
else if (achievement_fields[1].value_end && memcmp(achievement_fields[1].value_end - 4, "[m]", 3) == 0) {
len = strlen(achievement->title) - 3;
while (achievement->title[len - 1] == ' ')
--len;
((char*)achievement->title)[len] = '\0';
achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE;
}
rc_json_get_optional_float(&achievement->rarity, &achievement_fields[11], "Rarity", 100.0);
rc_json_get_optional_float(&achievement->rarity_hardcore, &achievement_fields[12], "RarityHardcore", 100.0);
++achievement;
}
}
@ -318,6 +360,11 @@ int rc_api_init_ping_request(rc_api_request_t* request, const rc_api_ping_reques
if (api_params->rich_presence && *api_params->rich_presence)
rc_url_builder_append_str_param(&builder, "m", api_params->rich_presence);
if (api_params->game_hash && *api_params->game_hash) {
rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore);
rc_url_builder_append_str_param(&builder, "x", api_params->game_hash);
}
request->post_data = rc_url_builder_finalize(&builder);
request->content_type = RC_CONTENT_TYPE_URLENCODED;
}

View File

@ -94,7 +94,14 @@ int rc_api_init_start_session_request(rc_api_request_t* request, const rc_api_st
rc_url_builder_init(&builder, &request->buffer, 48);
if (rc_api_url_build_dorequest(&builder, "startsession", api_params->username, api_params->api_token)) {
rc_url_builder_append_unum_param(&builder, "g", api_params->game_id);
if (api_params->game_hash && *api_params->game_hash) {
rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore);
rc_url_builder_append_str_param(&builder, "m", api_params->game_hash);
}
rc_url_builder_append_str_param(&builder, "l", RCHEEVOS_VERSION_STRING);
request->post_data = rc_url_builder_finalize(&builder);
request->content_type = RC_CONTENT_TYPE_URLENCODED;
}
@ -139,7 +146,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t
if (result != RC_OK || !response->response.succeeded)
return result;
if (rc_json_get_optional_array(&response->num_unlocks, &array_field, &response->response, &fields[2], "Unlocks") && response->num_unlocks) {
if (rc_json_get_optional_array(&response->num_unlocks, &array_field, &fields[2], "Unlocks") && response->num_unlocks) {
response->unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_unlocks * sizeof(rc_api_unlock_entry_t));
if (!response->unlocks)
return RC_OUT_OF_MEMORY;
@ -160,7 +167,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t
}
}
if (rc_json_get_optional_array(&response->num_hardcore_unlocks, &array_field, &response->response, &fields[3], "HardcoreUnlocks") && response->num_hardcore_unlocks) {
if (rc_json_get_optional_array(&response->num_hardcore_unlocks, &array_field, &fields[3], "HardcoreUnlocks") && response->num_hardcore_unlocks) {
response->hardcore_unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_hardcore_unlocks * sizeof(rc_api_unlock_entry_t));
if (!response->hardcore_unlocks)
return RC_OUT_OF_MEMORY;