Skip to content

Commit b77013b

Browse files
authored
add rc_client_create_subset_list (#486)
1 parent 253622a commit b77013b

File tree

6 files changed

+191
-1
lines changed

6 files changed

+191
-1
lines changed

include/rc_client.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,22 @@ RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client
364364

365365
RC_EXPORT void RC_CCONV rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary);
366366

367+
typedef struct rc_client_subset_list_t {
368+
const rc_client_subset_t** subsets;
369+
uint32_t num_subsets;
370+
} rc_client_subset_list_t;
371+
372+
/**
373+
* Creates a list of subsets for the currently loaded game.
374+
* Returns an allocated list that must be free'd by calling rc_client_destroy_subset_list.
375+
*/
376+
RC_EXPORT rc_client_subset_list_t* RC_CCONV rc_client_create_subset_list(rc_client_t* client);
377+
378+
/**
379+
* Destroys a list allocated by rc_client_create_subset_list_list.
380+
*/
381+
RC_EXPORT void RC_CCONV rc_client_destroy_subset_list(rc_client_subset_list_t* list);
382+
367383
/*****************************************************************************\
368384
| Fetch Game Hashes |
369385
\*****************************************************************************/
@@ -538,7 +554,7 @@ enum {
538554
RC_EXPORT rc_client_achievement_list_t* RC_CCONV rc_client_create_achievement_list(rc_client_t* client, int category, int grouping);
539555

540556
/**
541-
* Destroys a list allocated by rc_client_get_achievement_list.
557+
* Destroys a list allocated by rc_client_create_achievement_list.
542558
*/
543559
RC_EXPORT void RC_CCONV rc_client_destroy_achievement_list(rc_client_achievement_list_t* list);
544560

src/rc_client.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3487,6 +3487,58 @@ const rc_client_subset_t* rc_client_get_subset_info(rc_client_t* client, uint32_
34873487
return NULL;
34883488
}
34893489

3490+
rc_client_subset_list_t* rc_client_create_subset_list(rc_client_t* client)
3491+
{
3492+
rc_client_subset_list_info_t* list;
3493+
const rc_client_subset_info_t* subset;
3494+
const rc_client_subset_t** subset_ptr;
3495+
const uint32_t list_size = RC_ALIGN(sizeof(*list));
3496+
uint32_t num_subsets = 0;
3497+
3498+
if (!client)
3499+
return (rc_client_subset_list_t*)calloc(1, list_size);
3500+
3501+
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
3502+
if (client->state.external_client && client->state.external_client->create_subset_list)
3503+
return (rc_client_subset_list_t*)client->state.external_client->create_subset_list();
3504+
#endif
3505+
3506+
if (!client->game)
3507+
return (rc_client_subset_list_t*)calloc(1, list_size);
3508+
3509+
rc_mutex_lock(&client->state.mutex);
3510+
3511+
subset = client->game->subsets;
3512+
for (; subset; subset = subset->next) {
3513+
if (subset->active)
3514+
num_subsets++;
3515+
}
3516+
3517+
list = (rc_client_subset_list_info_t*)malloc(list_size + num_subsets * sizeof(rc_client_subset_t*));
3518+
list->public_.subsets = subset_ptr = (const rc_client_subset_t**)((uint8_t*)list + list_size);
3519+
3520+
subset = client->game->subsets;
3521+
for (; subset; subset = subset->next) {
3522+
if (subset->active)
3523+
*subset_ptr++ = &subset->public_;
3524+
}
3525+
3526+
rc_mutex_unlock(&client->state.mutex);
3527+
3528+
list->destroy_func = NULL;
3529+
list->public_.num_subsets = (uint32_t)(subset_ptr - list->public_.subsets);
3530+
return &list->public_;
3531+
}
3532+
3533+
void rc_client_destroy_subset_list(rc_client_subset_list_t* list)
3534+
{
3535+
rc_client_subset_list_info_t* info = (rc_client_subset_list_info_t*)list;
3536+
if (info->destroy_func)
3537+
info->destroy_func(info);
3538+
else
3539+
free(list);
3540+
}
3541+
34903542
/* ===== Fetch Game Hashes ===== */
34913543

34923544
typedef struct rc_client_fetch_hash_library_callback_data_t {

src/rc_client_external.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_fetch_lead
6161
typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_fetch_leaderboard_entries_around_user_func_t)(rc_client_t* client,
6262
uint32_t leaderboard_id, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata);
6363

64+
/* NOTE: rc_client_external_create_subset_list_func_t returns an internal wrapper structure which contains the public list
65+
* and a destructor function. */
66+
struct rc_client_subset_list_info_t;
67+
typedef struct rc_client_subset_list_info_t* (RC_CCONV* rc_client_external_create_subset_list_func_t)();
68+
6469

6570
typedef size_t (RC_CCONV *rc_client_external_progress_size_func_t)(void);
6671
typedef int (RC_CCONV *rc_client_external_serialize_progress_func_t)(uint8_t* buffer, size_t buffer_size);
@@ -144,6 +149,9 @@ typedef struct rc_client_external_t
144149
rc_client_external_get_user_game_summary_func_t get_user_game_summary_v5;
145150
rc_client_external_get_user_subset_summary_func_t get_user_subset_summary;
146151

152+
/* VERSION 6 */
153+
rc_client_external_create_subset_list_func_t create_subset_list;
154+
147155
} rc_client_external_t;
148156

149157
#define RC_CLIENT_EXTERNAL_VERSION 5

src/rc_client_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ typedef struct rc_client_subset_info_t {
222222
uint8_t pending_events;
223223
} rc_client_subset_info_t;
224224

225+
struct rc_client_subset_list_info_t;
226+
typedef void (RC_CCONV* rc_client_destroy_subset_list_func_t)(struct rc_client_subset_list_info_t* list);
227+
228+
typedef struct rc_client_subset_list_info_t {
229+
rc_client_subset_list_t public_;
230+
rc_client_destroy_subset_list_func_t destroy_func;
231+
} rc_client_subset_list_info_t;
232+
225233
/*****************************************************************************\
226234
| Game |
227235
\*****************************************************************************/

test/test_rc_client.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4072,6 +4072,50 @@ static void test_load_subset(void)
40724072
rc_client_destroy(g_client);
40734073
}
40744074

4075+
static void test_subset_list(void)
4076+
{
4077+
rc_client_subset_list_t* list;
4078+
const rc_client_subset_t* subset;
4079+
4080+
g_client = mock_client_game_loaded(patchdata_subset, no_unlocks);
4081+
4082+
list = rc_client_create_subset_list(g_client);
4083+
ASSERT_PTR_NOT_NULL(list);
4084+
if (list) {
4085+
ASSERT_NUM_EQUALS(list->num_subsets, 2);
4086+
4087+
subset = list->subsets[0];
4088+
ASSERT_NUM_EQUALS(subset->id, 1111);
4089+
ASSERT_STR_EQUALS(subset->title, "Sample Game");
4090+
ASSERT_STR_EQUALS(subset->badge_name, "112233");
4091+
ASSERT_NUM_EQUALS(subset->num_achievements, 7);
4092+
ASSERT_NUM_EQUALS(subset->num_leaderboards, 7);
4093+
ASSERT_STR_EQUALS(subset->badge_url, "http://server/Images/112233.png");
4094+
4095+
subset = list->subsets[1];
4096+
ASSERT_NUM_EQUALS(subset->id, 2345);
4097+
ASSERT_STR_EQUALS(subset->title, "Bonus");
4098+
ASSERT_STR_EQUALS(subset->badge_name, "112234");
4099+
ASSERT_NUM_EQUALS(subset->num_achievements, 3);
4100+
ASSERT_NUM_EQUALS(subset->num_leaderboards, 2);
4101+
ASSERT_STR_EQUALS(subset->badge_url, "http://server/Images/112234.png");
4102+
4103+
rc_client_destroy_subset_list(list);
4104+
}
4105+
4106+
rc_client_unload_game(g_client);
4107+
ASSERT_PTR_NULL(g_client->game);
4108+
4109+
list = rc_client_create_subset_list(g_client);
4110+
ASSERT_PTR_NOT_NULL(list);
4111+
if (list) {
4112+
ASSERT_NUM_EQUALS(list->num_subsets, 0);
4113+
rc_client_destroy_subset_list(list);
4114+
}
4115+
4116+
rc_client_destroy(g_client);
4117+
}
4118+
40754119
/* ----- achievement list ----- */
40764120

40774121
static void test_achievement_list_simple(void)
@@ -10163,6 +10207,7 @@ void test_client(void) {
1016310207

1016410208
/* subset */
1016510209
TEST(test_load_subset);
10210+
TEST(test_subset_list);
1016610211

1016710212
/* achievements */
1016810213
TEST(test_achievement_list_simple);

test/test_rc_client_external.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,66 @@ static void test_get_subset_info(void)
13351335
rc_client_destroy(g_client);
13361336
}
13371337

1338+
static void rc_client_external_destroy_subset_list(rc_client_subset_list_info_t* list)
1339+
{
1340+
g_external_event = "destroyed";
1341+
free(list);
1342+
}
1343+
1344+
static rc_client_subset_list_info_t* rc_client_external_create_subset_list_v6()
1345+
{
1346+
rc_client_subset_list_info_t* list;
1347+
1348+
list = (rc_client_subset_list_info_t*)calloc(1, sizeof(*list) + sizeof(rc_client_subset_t*) * 2);
1349+
if (list) {
1350+
const rc_client_subset_t** subset;
1351+
rc_client_subset_t* mutable_subset;
1352+
list->public_.num_subsets = 2;
1353+
list->public_.subsets = subset = (const rc_client_subset_t**)((uint8_t*)list + sizeof(*list));
1354+
*subset++ = rc_client_external_get_subset_info_v3(1111);
1355+
*subset = rc_client_external_get_subset_info_v3(2345);
1356+
mutable_subset = (rc_client_subset_t*)*subset;
1357+
mutable_subset->title = "Bonus";
1358+
mutable_subset->num_achievements = 1;
1359+
mutable_subset->num_leaderboards = 0;
1360+
1361+
list->destroy_func = rc_client_external_destroy_subset_list;
1362+
}
1363+
1364+
return list;
1365+
}
1366+
1367+
static void test_create_subset_list(void)
1368+
{
1369+
rc_client_subset_list_t* list;
1370+
1371+
g_client = mock_client_with_external();
1372+
g_client->state.external_client->create_subset_list = rc_client_external_create_subset_list_v6;
1373+
1374+
list = rc_client_create_subset_list(g_client);
1375+
ASSERT_PTR_NOT_NULL(list);
1376+
ASSERT_NUM_EQUALS(list->num_subsets, 2);
1377+
ASSERT_PTR_NOT_NULL(list->subsets);
1378+
ASSERT_NUM_EQUALS(list->subsets[0]->id, 1111);
1379+
ASSERT_STR_EQUALS(list->subsets[0]->title, "Subset Title");
1380+
ASSERT_STR_EQUALS(list->subsets[0]->badge_name, "BDG001");
1381+
ASSERT_NUM_EQUALS(list->subsets[0]->num_achievements, 2);
1382+
ASSERT_NUM_EQUALS(list->subsets[0]->num_leaderboards, 1);
1383+
ASSERT_STR_EQUALS(list->subsets[0]->badge_url, "/Badge/BDG001.png");
1384+
ASSERT_NUM_EQUALS(list->subsets[1]->id, 2345);
1385+
ASSERT_STR_EQUALS(list->subsets[1]->title, "Bonus");
1386+
ASSERT_STR_EQUALS(list->subsets[1]->badge_name, "BDG001");
1387+
ASSERT_NUM_EQUALS(list->subsets[1]->num_achievements, 1);
1388+
ASSERT_NUM_EQUALS(list->subsets[1]->num_leaderboards, 0);
1389+
ASSERT_STR_EQUALS(list->subsets[1]->badge_url, "/Badge/BDG001.png");
1390+
1391+
rc_client_destroy_subset_list(list);
1392+
1393+
ASSERT_STR_EQUALS(g_external_event, "destroyed");
1394+
1395+
rc_client_destroy(g_client);
1396+
}
1397+
13381398
static void test_unload_game(void)
13391399
{
13401400
g_client = mock_client_with_external();
@@ -2068,6 +2128,7 @@ void test_client_external(void) {
20682128
TEST(test_v3_subset_field_offsets);
20692129
TEST(test_get_subset_info_v1);
20702130
TEST(test_get_subset_info);
2131+
TEST(test_create_subset_list);
20712132

20722133
/* achievements */
20732134
TEST(test_v1_achievement_field_offsets);

0 commit comments

Comments
 (0)