Skip to content

Commit

Permalink
allow client to prevent rich presence submission (#284)
Browse files Browse the repository at this point in the history
Jamiras authored Oct 23, 2023
1 parent d24d279 commit 3d99026
Showing 3 changed files with 99 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/rc_client.c
Original file line number Diff line number Diff line change
@@ -3978,8 +3978,11 @@ static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, r
char buffer[256];
int result;

rc_runtime_get_richpresence(&client->game->runtime, buffer, sizeof(buffer),
client->state.legacy_peek, client, NULL);
if (!client->callbacks.rich_presence_override ||
!client->callbacks.rich_presence_override(client, buffer, sizeof(buffer))) {
rc_runtime_get_richpresence(&client->game->runtime, buffer, sizeof(buffer),
client->state.legacy_peek, client, NULL);
}

memset(&api_params, 0, sizeof(api_params));
api_params.username = client->user.username;
2 changes: 2 additions & 0 deletions src/rc_client_internal.h
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ typedef void (*rc_client_post_process_game_data_response_t)(const rc_api_server_
struct rc_api_fetch_game_data_response_t* game_data_response, rc_client_t* client, void* userdata);
typedef int (*rc_client_can_submit_achievement_unlock_t)(uint32_t achievement_id, rc_client_t* client);
typedef int (*rc_client_can_submit_leaderboard_entry_t)(uint32_t leaderboard_id, rc_client_t* client);
typedef int (*rc_client_rich_presence_override_t)(rc_client_t* client, char buffer[], size_t buffersize);

typedef struct rc_client_callbacks_t {
rc_client_read_memory_func_t read_memory;
@@ -30,6 +31,7 @@ typedef struct rc_client_callbacks_t {
rc_client_post_process_game_data_response_t post_process_game_data_response;
rc_client_can_submit_achievement_unlock_t can_submit_achievement_unlock;
rc_client_can_submit_leaderboard_entry_t can_submit_leaderboard_entry;
rc_client_rich_presence_override_t rich_presence_override;

void* client_data;
} rc_client_callbacks_t;
92 changes: 92 additions & 0 deletions test/test_rc_client.c
Original file line number Diff line number Diff line change
@@ -7253,6 +7253,96 @@ static void test_do_frame_ping_rich_presence(void)
rc_client_destroy(g_client);
}

static int rc_client_callback_rich_presence_override_allow(rc_client_t* client, char buffer[], size_t buffersize)
{
memcpy(buffer, "Custom", 7);
return 0;
}

static int rc_client_callback_rich_presence_override_replace(rc_client_t* client, char buffer[], size_t buffersize)
{
memcpy(buffer, "Custom", 7);
return 6;
}

static void test_do_frame_ping_rich_presence_override_allowed(void)
{
uint8_t memory[64];
memset(memory, 0, sizeof(memory));

g_client = mock_client_game_loaded(patchdata_exhaustive, no_unlocks);
g_client->callbacks.rich_presence_override = rc_client_callback_rich_presence_override_allow;

ASSERT_PTR_NOT_NULL(g_client->game);
if (g_client->game)
{
rc_client_scheduled_callback_t ping_callback;

ASSERT_PTR_NOT_NULL(g_client->state.scheduled_callbacks);
ping_callback = g_client->state.scheduled_callbacks->callback;

ASSERT_NUM_EQUALS(g_client->state.scheduled_callbacks->when, g_now + 30 * 1000);
g_now += 30 * 1000;

mock_memory(memory, sizeof(memory));
memory[0x03] = 25;

/* before rc_client_do_frame, memory will not have been read. all values will be 0 */
mock_api_response("r=ping&u=Username&t=ApiToken&g=1234&m=Points%3a0", "{\"Success\":true}");

rc_client_idle(g_client);

ASSERT_PTR_NOT_NULL(g_client->state.scheduled_callbacks);
ASSERT_PTR_EQUALS(g_client->state.scheduled_callbacks->callback, ping_callback);
ASSERT_NUM_EQUALS(g_client->state.scheduled_callbacks->when, g_now + 120 * 1000);
g_now += 120 * 1000;

/* rc_client_do_frame will update the memory, so the message will contain appropriate data */
mock_api_response("r=ping&u=Username&t=ApiToken&g=1234&m=Points%3a25", "{\"Success\":true}");
}

rc_client_destroy(g_client);
}

static void test_do_frame_ping_rich_presence_override_replaced(void)
{
uint8_t memory[64];
memset(memory, 0, sizeof(memory));

g_client = mock_client_game_loaded(patchdata_exhaustive, no_unlocks);
g_client->callbacks.rich_presence_override = rc_client_callback_rich_presence_override_replace;

ASSERT_PTR_NOT_NULL(g_client->game);
if (g_client->game)
{
rc_client_scheduled_callback_t ping_callback;

ASSERT_PTR_NOT_NULL(g_client->state.scheduled_callbacks);
ping_callback = g_client->state.scheduled_callbacks->callback;

ASSERT_NUM_EQUALS(g_client->state.scheduled_callbacks->when, g_now + 30 * 1000);
g_now += 30 * 1000;

mock_memory(memory, sizeof(memory));
memory[0x03] = 25;

/* before rc_client_do_frame, can_submit only ignores the m parameter. ping still occurs */
mock_api_response("r=ping&u=Username&t=ApiToken&g=1234&m=Custom", "{\"Success\":true}");

rc_client_idle(g_client);

ASSERT_PTR_NOT_NULL(g_client->state.scheduled_callbacks);
ASSERT_PTR_EQUALS(g_client->state.scheduled_callbacks->callback, ping_callback);
ASSERT_NUM_EQUALS(g_client->state.scheduled_callbacks->when, g_now + 120 * 1000);
g_now += 120 * 1000;

/* ping still happens every two minutes, even if message not provided */
mock_api_response("r=ping&u=Username&t=ApiToken&g=1234&m=Custom", "{\"Success\":true}");
}

rc_client_destroy(g_client);
}

static void test_reset_hides_widgets(void)
{
const rc_client_leaderboard_t* leaderboard;
@@ -8171,6 +8261,8 @@ void test_client(void) {
/* ping */
TEST(test_idle_ping);
TEST(test_do_frame_ping_rich_presence);
TEST(test_do_frame_ping_rich_presence_override_allowed);
TEST(test_do_frame_ping_rich_presence_override_replaced);

/* reset */
TEST(test_reset_hides_widgets);

0 comments on commit 3d99026

Please sign in to comment.