Skip to content

Commit

Permalink
plumb type and rarity through to rc_client
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamiras committed Nov 27, 2023
1 parent 2401a8a commit 8a4155f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
11 changes: 11 additions & 0 deletions include/rc_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,13 @@ enum {
RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL = RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE | RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL
};

enum {
RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD = 0,
RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE = 1,
RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION = 2,
RC_CLIENT_ACHIEVEMENT_TYPE_WIN = 3
};

enum {
RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN = 0,
RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED = 1,
Expand Down Expand Up @@ -329,6 +336,10 @@ typedef struct rc_client_achievement_t {
uint8_t category;
uint8_t bucket;
uint8_t unlocked;
/* minimum version: 11.1 */
float rarity;
float rarity_hardcore;
uint8_t type;
} rc_client_achievement_t;

/**
Expand Down
3 changes: 3 additions & 0 deletions src/rc_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,9 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
achievement->public_.points = read->points;
achievement->public_.category = (read->category != RC_ACHIEVEMENT_CATEGORY_CORE) ?
RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL : RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE;
achievement->public_.rarity = read->rarity;
achievement->public_.rarity_hardcore = read->rarity_hardcore;
achievement->public_.type = read->type; /* assert: mapping is 1:1 */

memaddr = read->definition;
rc_runtime_checksum(memaddr, achievement->md5);
Expand Down
97 changes: 97 additions & 0 deletions test/test_rc_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ static void* g_callback_userdata = &g_client; /* dummy object to use for callbac
"\"Description\":\"Desc " id "\",\"Flags\":3,\"Points\":5,\"MemAddr\":\"" memaddr "\"," \
"\"Author\":\"User1\",\"BadgeName\":\"00" id "\",\"Created\":1367266583,\"Modified\":1376929305}"

#define TYPED_ACHIEVEMENT_JSON(id, memaddr, type, rarity, rarity_hardcore) "{\"ID\":" id ",\"Title\":\"Achievement " id "\"," \
"\"Description\":\"Desc " id "\",\"Flags\":3,\"Points\":5,\"MemAddr\":\"" memaddr "\"," \
"\"Type\":\"" type "\",\"Rarity\":" rarity ",\"RarityHardcore\":" rarity_hardcore "," \
"\"Author\":\"User1\",\"BadgeName\":\"00" id "\",\"Created\":1367266583,\"Modified\":1376929305}"

#define GENERIC_LEADERBOARD_JSON(id, memaddr, format) "{\"ID\":" id ",\"Title\":\"Leaderboard " id "\"," \
"\"Description\":\"Desc " id "\",\"Mem\":\"" memaddr "\",\"Format\":\"" format "\"}"

Expand Down Expand Up @@ -151,6 +156,30 @@ static const char* patchdata_exhaustive = "{\"Success\":true,\"PatchData\":{"
"\"RichPresencePatch\":\"Display:\\r\\nPoints:@Number(0xH0003)\\r\\n\""
"}}";


static const char* patchdata_exhaustive_typed = "{\"Success\":true,\"PatchData\":{"
"\"ID\":1234,\"Title\":\"Sample Game\",\"ConsoleID\":7,\"ImageIcon\":\"/Images/112233.png\","
"\"Achievements\":["
TYPED_ACHIEVEMENT_JSON("5", "0xH0005=5", "", "100.0", "99.5") ","
TYPED_ACHIEVEMENT_JSON("6", "M:0xH0006=6", "progression", "95.3", "84.7") ","
TYPED_ACHIEVEMENT_JSON("7", "T:0xH0007=7_0xH0001=1", "missable", "47.6", "38.2") ","
TYPED_ACHIEVEMENT_JSON("8", "0xH0008=8", "progression", "86.0", "73.1") ","
TYPED_ACHIEVEMENT_JSON("9", "0xH0009=9", "win_condition", "81.4", "66.4") ","
TYPED_ACHIEVEMENT_JSON("70", "M:0xX0010=100000", "missable", "11.4", "6.3") ","
TYPED_ACHIEVEMENT_JSON("71", "G:0xX0010=100000", "", "8.7", "3.8")
"],"
"\"Leaderboards\":["
GENERIC_LEADERBOARD_JSON("44", "STA:0xH000B=1::CAN:0xH000C=1::SUB:0xH000D=1::VAL:0x 000E", "SCORE") ","
GENERIC_LEADERBOARD_JSON("45", "STA:0xH000A=1::CAN:0xH000C=2::SUB:0xH000D=1::VAL:0xH000E", "SCORE") "," /* different size */
GENERIC_LEADERBOARD_JSON("46", "STA:0xH000A=1::CAN:0xH000C=3::SUB:0xH000D=1::VAL:0x 000E", "VALUE") "," /* different format */
GENERIC_LEADERBOARD_JSON("47", "STA:0xH000A=1::CAN:0xH000C=4::SUB:0xH000D=2::VAL:0x 000E", "SCORE") "," /* different submit */
GENERIC_LEADERBOARD_JSON("48", "STA:0xH000A=2::CAN:0xH000C=5::SUB:0xH000D=1::VAL:0x 000E", "SCORE") "," /* different start */
GENERIC_LEADERBOARD_JSON("51", "STA:0xH000A=3::CAN:0xH000C=6::SUB:0xH000D=1::VAL:M:0xH0009=1", "VALUE") "," /* hit count */
GENERIC_LEADERBOARD_JSON("52", "STA:0xH000B=3::CAN:0xH000C=7::SUB:0xH000D=1::VAL:M:0xH0009=1", "VALUE") /* hit count */
"],"
"\"RichPresencePatch\":\"Display:\\r\\nPoints:@Number(0xH0003)\\r\\n\""
"}}";

static const char* patchdata_big_ids = "{\"Success\":true,\"PatchData\":{"
"\"ID\":1234,\"Title\":\"Sample Game\",\"ConsoleID\":7,\"ImageIcon\":\"/Images/112233.png\","
"\"Achievements\":["
Expand Down Expand Up @@ -1148,6 +1177,25 @@ static void test_get_user_game_summary_with_unsupported_unlocks(void)
rc_client_destroy(g_client);
}

static void test_get_user_game_summary_with_unofficial_off(void)
{
rc_client_user_game_summary_t summary;

g_client = mock_client_logged_in();
rc_client_set_unofficial_enabled(g_client, 0);
mock_client_load_game(patchdata_unofficial_unsupported, no_unlocks);

rc_client_get_user_game_summary(g_client, &summary);
ASSERT_NUM_EQUALS(summary.num_core_achievements, 2);
ASSERT_NUM_EQUALS(summary.num_unofficial_achievements, 1);
ASSERT_NUM_EQUALS(summary.num_unsupported_achievements, 1);
ASSERT_NUM_EQUALS(summary.num_unlocked_achievements, 0);

ASSERT_NUM_EQUALS(summary.points_core, 7);
ASSERT_NUM_EQUALS(summary.points_unlocked, 0);

rc_client_destroy(g_client);
}

/* ----- load game ----- */

Expand Down Expand Up @@ -5387,6 +5435,53 @@ static void test_do_frame_achievement_trigger_subset(void)
rc_client_destroy(g_client);
}

static void test_do_frame_achievement_trigger_rarity(void)
{
rc_client_event_t* event;
uint8_t memory[64];
memset(memory, 0, sizeof(memory));

g_client = mock_client_game_loaded(patchdata_exhaustive_typed, no_unlocks);

ASSERT_PTR_NOT_NULL(g_client->game);
if (g_client->game)
{
const uint32_t num_active = g_client->game->runtime.trigger_count;
mock_memory(memory, sizeof(memory));

mock_api_response("r=awardachievement&u=Username&t=ApiToken&a=8&h=1&m=0123456789ABCDEF&v=da80b659c2b858e13ddd97077647b217",
"{\"Success\":true,\"Score\":5432,\"SoftcoreScore\":777,\"AchievementID\":8,\"AchievementsRemaining\":11}");

event_count = 0;
rc_client_do_frame(g_client);
ASSERT_NUM_EQUALS(event_count, 0);

memory[8] = 8;
rc_client_do_frame(g_client);
ASSERT_NUM_EQUALS(event_count, 1);

event = find_event(RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED, 8);
ASSERT_PTR_NOT_NULL(event);
ASSERT_NUM_EQUALS(event->achievement->state, RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED);
ASSERT_NUM_EQUALS(event->achievement->unlocked, RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH);
ASSERT_NUM_NOT_EQUALS(event->achievement->unlock_time, 0);
ASSERT_NUM_EQUALS(event->achievement->bucket, RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED);
ASSERT_NUM_EQUALS(event->achievement->type, RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION);
ASSERT_FLOAT_EQUALS(event->achievement->rarity, 86.0f);
ASSERT_FLOAT_EQUALS(event->achievement->rarity_hardcore, 73.1f);
ASSERT_PTR_EQUALS(event->achievement, rc_client_get_achievement_info(g_client, 8));

ASSERT_NUM_EQUALS(g_client->game->runtime.trigger_count, num_active - 1);
ASSERT_NUM_EQUALS(g_client->user.score, 5432);
ASSERT_NUM_EQUALS(g_client->user.score_softcore, 777);

event_count = 0;
rc_client_do_frame(g_client);
ASSERT_NUM_EQUALS(event_count, 0);
}

rc_client_destroy(g_client);
}

static void test_do_frame_achievement_measured(void)
{
Expand Down Expand Up @@ -8061,6 +8156,7 @@ void test_client(void) {
TEST(test_get_user_game_summary_encore_mode);
TEST(test_get_user_game_summary_with_unsupported_and_unofficial);
TEST(test_get_user_game_summary_with_unsupported_unlocks);
TEST(test_get_user_game_summary_with_unofficial_off);

/* load game */
TEST(test_load_game_required_fields);
Expand Down Expand Up @@ -8171,6 +8267,7 @@ void test_client(void) {
TEST(test_do_frame_achievement_trigger_automatic_retry_custom_timeout);
TEST(test_do_frame_achievement_trigger_automatic_retry_generic_empty_response);
TEST(test_do_frame_achievement_trigger_subset);
TEST(test_do_frame_achievement_trigger_rarity);
TEST(test_do_frame_achievement_measured);
TEST(test_do_frame_achievement_measured_progress_event);
TEST(test_do_frame_achievement_challenge_indicator);
Expand Down

0 comments on commit 8a4155f

Please sign in to comment.