Skip to content

Commit

Permalink
(cheevos) inform user when server is unreachable (#15970)
Browse files Browse the repository at this point in the history
* ensure game placard is loaded on main thread

* show on-screen indicator while disconnected

* show server unreachable message in achievements menu

* remove comment
  • Loading branch information
Jamiras authored Dec 2, 2023
1 parent 12b6b68 commit 93e5566
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 7 deletions.
67 changes: 62 additions & 5 deletions cheevos/cheevos.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ static rcheevos_locals_t rcheevos_locals =
{{0}},/* memory */
#ifdef HAVE_THREADS
CMD_EVENT_NONE, /* queued_command */
false, /* game_placard_requested */
#endif
#ifndef HAVE_RC_CLIENT
"", /* displayname */
Expand Down Expand Up @@ -134,6 +135,9 @@ rcheevos_locals_t* get_rcheevos_locals(void)
Supporting functions.
*****************************************************************************/

#define CMD_CHEEVOS_NON_COMMAND -1
static void rcheevos_show_game_placard(void);

#ifndef CHEEVOS_VERBOSE
void rcheevos_log(const char* fmt, ...)
{
Expand Down Expand Up @@ -602,6 +606,39 @@ static void rcheevos_server_error(const char* api_name, const char* message)
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
}

static void rcheevos_server_disconnected()
{
CHEEVOS_LOG(RCHEEVOS_TAG "Unable to communicate with RetroAchievements server\n");

/* always show message - even with widget. it helps the user understand what the widget is for */
{
const char* message = msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_SERVER_DISCONNECTED);
runloop_msg_queue_push(message, 0, 3 * 60, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING);
}

#if defined(HAVE_GFX_WIDGETS)
if (gfx_widgets_ready())
gfx_widget_set_cheevos_disconnect(true);
#endif
}

static void rcheevos_server_reconnected()
{
CHEEVOS_LOG(RCHEEVOS_TAG "All pending requests synced to RetroAchievements server\n");

{
const char* message = msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_SERVER_RECONNECTED);
runloop_msg_queue_push(message, 0, 3 * 60, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_SUCCESS);
}

#if defined(HAVE_GFX_WIDGETS)
if (gfx_widgets_ready())
gfx_widget_set_cheevos_disconnect(false);
#endif
}

static void rcheevos_client_event_handler(const rc_client_event_t* event, rc_client_t* client)
{
switch (event->type)
Expand Down Expand Up @@ -657,10 +694,10 @@ static void rcheevos_client_event_handler(const rc_client_event_t* event, rc_cli
rcheevos_server_error(event->server_error->api, event->server_error->error_message);
break;
case RC_CLIENT_EVENT_DISCONNECTED:
CHEEVOS_LOG(RCHEEVOS_TAG "Unable to communicate with RetroAchievements server");
rcheevos_server_disconnected();
break;
case RC_CLIENT_EVENT_RECONNECTED:
CHEEVOS_LOG(RCHEEVOS_TAG "All pending requests synced to RetroAchievements server");
rcheevos_server_reconnected();
break;
default:
#ifndef NDEBUG
Expand Down Expand Up @@ -1202,9 +1239,12 @@ bool rcheevos_unload(void)
/* Clean up after completed tasks */
task_queue_check();
}
#endif
#endif

#ifdef HAVE_THREADS
rcheevos_locals.queued_command = CMD_EVENT_NONE;
#endif
rcheevos_locals.game_placard_requested = false;
#endif

if (rcheevos_locals.memory.count > 0)
Expand Down Expand Up @@ -1866,8 +1906,16 @@ void rcheevos_test(void)
#ifdef HAVE_THREADS
if (rcheevos_locals.queued_command != CMD_EVENT_NONE)
{
command_event(rcheevos_locals.queued_command, NULL);
if (rcheevos_locals.queued_command != CMD_CHEEVOS_NON_COMMAND)
command_event(rcheevos_locals.queued_command, NULL);

rcheevos_locals.queued_command = CMD_EVENT_NONE;

if (rcheevos_locals.game_placard_requested)
{
rcheevos_locals.game_placard_requested = false;
rcheevos_show_game_placard();
}
}
#endif

Expand Down Expand Up @@ -2414,7 +2462,16 @@ static void rcheevos_client_load_game_callback(int result,
rc_client_set_read_memory_function(client, rcheevos_client_read_memory);
}

rcheevos_show_game_placard();
#ifdef HAVE_THREADS
if (!task_is_on_main_thread())
{
/* have to "schedule" this. game image should not be loaded on background thread */
rcheevos_locals.queued_command = CMD_CHEEVOS_NON_COMMAND;
rcheevos_locals.game_placard_requested = true;
}
else
rcheevos_show_game_placard();
#endif

rcheevos_finalize_game_load(client);

Expand Down
1 change: 1 addition & 0 deletions cheevos/cheevos_locals.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ typedef struct rcheevos_locals_t

#ifdef HAVE_THREADS
enum event_command queued_command; /* action queued by background thread to be run on main thread */
bool game_placard_requested; /* request to display game placard */
#endif

#ifndef HAVE_RC_CLIENT
Expand Down
16 changes: 15 additions & 1 deletion cheevos/cheevos_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "../deps/rcheevos/include/rc_runtime_types.h"
#include "../deps/rcheevos/include/rc_api_runtime.h"
#include "../deps/rcheevos/src/rc_client_internal.h"

#include "../menu/menu_driver.h"
#include "../menu/menu_entries.h"
Expand Down Expand Up @@ -295,6 +296,15 @@ void rcheevos_menu_populate(void* data)
rcheevos_menu_reset_badges();
rcheevos_locals->menuitem_count = 0;

if (rcheevos_locals->client->state.disconnect)
{
menu_entries_append(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_SERVER_UNREACHABLE),
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_SERVER_UNREACHABLE),
MENU_ENUM_LABEL_ACHIEVEMENT_SERVER_UNREACHABLE,
MENU_INFO_ACHIEVEMENTS_SERVER_UNREACHABLE, 0, 0, NULL);
}

if (game && game->id != 0)
{
/* first menu item is the Pause/Resume Hardcore option (unless hardcore is completely disabled) */
Expand Down Expand Up @@ -466,7 +476,11 @@ uintptr_t rcheevos_get_badge_texture(const char* badge, bool locked, bool downlo
return 0;

/* OpenGL driver crashes if gfx_display_reset_textures_list is called on a background thread */
retro_assert(task_is_on_main_thread());
if (!task_is_on_main_thread())
{
CHEEVOS_ERR(RCHEEVOS_TAG "attempt to load badge %s from background thread", badge);
retro_assert(task_is_on_main_thread());
}

snprintf(badge_file, sizeof(badge_file), "%s%s%s", badge,
locked ? "_lock" : "", FILE_PATH_PNG_EXTENSION);
Expand Down
1 change: 1 addition & 0 deletions gfx/gfx_widgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ void gfx_widgets_clear_leaderboard_displays(void);
void gfx_widgets_set_challenge_display(unsigned id, const char* badge);
void gfx_widgets_clear_challenge_displays(void);
void gfx_widget_set_achievement_progress(const char* badge, const char* progress);
void gfx_widget_set_cheevos_disconnect(bool visible);
#endif

/* TODO/FIXME/WARNING: Not thread safe! */
Expand Down
47 changes: 46 additions & 1 deletion gfx/widgets/gfx_widget_leaderboard_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct progress_tracker_info

#define CHEEVO_LBOARD_FIRST_FIXED_CHAR 0x2D /* -./0123456789: */
#define CHEEVO_LBOARD_LAST_FIXED_CHAR 0x3A

/* TODO: rename; this file handles all achievement tracker information, not just leaderboards */
struct gfx_widget_leaderboard_display_state
{
#ifdef HAVE_THREADS
Expand All @@ -64,6 +66,7 @@ struct gfx_widget_leaderboard_display_state
unsigned challenge_count;
uint16_t char_width[CHEEVO_LBOARD_LAST_FIXED_CHAR - CHEEVO_LBOARD_FIRST_FIXED_CHAR + 1];
uint16_t fixed_char_width;
bool disconnected;
};

typedef struct gfx_widget_leaderboard_display_state gfx_widget_leaderboard_display_state_t;
Expand Down Expand Up @@ -109,7 +112,10 @@ static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;

/* if there's nothing to display, just bail */
if (state->tracker_count == 0 && state->challenge_count == 0 && state->progress_tracker.show_until == 0)
if (state->tracker_count == 0 &&
state->challenge_count == 0 &&
state->progress_tracker.show_until == 0 &&
!state->disconnected)
return;

#ifdef HAVE_THREADS
Expand Down Expand Up @@ -335,6 +341,38 @@ static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
TEXT_COLOR_INFO, TEXT_ALIGN_LEFT, true);
}
}

if (state->disconnected)
{
const char* disconnected_text = "! RA !";
const unsigned disconnect_widget_width = font_driver_get_message_width(
state->dispwidget_ptr->gfx_widget_fonts.msg_queue.font,
disconnected_text, 0, 1) + CHEEVO_LBOARD_DISPLAY_PADDING * 2;
const unsigned disconnect_widget_height =
p_dispwidget->gfx_widget_fonts.msg_queue.line_height + (CHEEVO_LBOARD_DISPLAY_PADDING - 1) * 2;
x = video_width - disconnect_widget_width - spacing;
y -= disconnect_widget_height + spacing;

/* Backdrop */
gfx_display_draw_quad(
p_disp,
video_info->userdata,
video_width, video_height,
(int)x, (int)y, disconnect_widget_width, disconnect_widget_height,
video_width, video_height,
p_dispwidget->backdrop_orig,
NULL);

/* Text */
char_x = (float)(x + CHEEVO_LBOARD_DISPLAY_PADDING);
char_y = (float)(y + disconnect_widget_height - (CHEEVO_LBOARD_DISPLAY_PADDING - 1)
- p_dispwidget->gfx_widget_fonts.msg_queue.line_descender);

gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.msg_queue,
disconnected_text, char_x, char_y,
video_width, video_height,
TEXT_COLOR_INFO, TEXT_ALIGN_LEFT, true);
}
}

#ifdef HAVE_THREADS
Expand Down Expand Up @@ -542,6 +580,13 @@ void gfx_widget_set_achievement_progress(const char* badge, const char* progress
video_driver_texture_unload(&old_badge_id);
}

void gfx_widget_set_cheevos_disconnect(bool value)
{
gfx_widget_leaderboard_display_state_t* state = &p_w_leaderboard_display_st;
state->disconnected = value;
}


const gfx_widget_t gfx_widget_leaderboard_display = {
&gfx_widget_leaderboard_display_init,
&gfx_widget_leaderboard_display_free,
Expand Down
16 changes: 16 additions & 0 deletions intl/msg_hash_us.h
Original file line number Diff line number Diff line change
Expand Up @@ -9691,6 +9691,22 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_ACHIEVEMENT_RESUME,
"Resume achievements hardcore mode for the current session. This action will disable cheats, rewind, slow-motion, and loading save states and reset the current game."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_SERVER_UNREACHABLE,
"RetroAchievements server is unreachable"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_ACHIEVEMENT_SERVER_UNREACHABLE,
"One or more achievement unlocks did not make it to the server. The unlocks will be retried as long as you leave the app open."
)
MSG_HASH(
MENU_ENUM_LABEL_CHEEVOS_SERVER_DISCONNECTED,
"RetroAchievements server is unreachable. Will retry until successful or the app is closed."
)
MSG_HASH(
MENU_ENUM_LABEL_CHEEVOS_SERVER_RECONNECTED,
"All pending requests have succesfully been synced to the RetroAchievements server."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_NOT_LOGGED_IN,
"Not logged in"
Expand Down
4 changes: 4 additions & 0 deletions menu/cbs/menu_cbs_sublabel.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_information_list_list, MENU_
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_achievement_list, MENU_ENUM_SUBLABEL_ACHIEVEMENT_LIST)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_achievement_pause_cancel, MENU_ENUM_SUBLABEL_ACHIEVEMENT_PAUSE_CANCEL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_achievement_resume_cancel, MENU_ENUM_SUBLABEL_ACHIEVEMENT_RESUME_CANCEL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_achievement_server_unreachable,MENU_ENUM_SUBLABEL_ACHIEVEMENT_SERVER_UNREACHABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_enable, MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_test_unofficial, MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_hardcore_mode_enable, MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE)
Expand Down Expand Up @@ -4564,6 +4565,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_ACHIEVEMENT_RESUME_CANCEL:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_achievement_resume_cancel);
break;
case MENU_ENUM_LABEL_ACHIEVEMENT_SERVER_UNREACHABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_achievement_server_unreachable);
break;
case MENU_ENUM_LABEL_CHEEVOS_UNLOCKED_ENTRY:
case MENU_ENUM_LABEL_CHEEVOS_UNLOCKED_ENTRY_HARDCORE:
case MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY:
Expand Down
2 changes: 2 additions & 0 deletions menu/drivers/ozone.c
Original file line number Diff line number Diff line change
Expand Up @@ -2290,6 +2290,8 @@ static uintptr_t ozone_entries_icon_get_texture(
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_RELOAD];
case MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_PAUSE];
case MENU_INFO_ACHIEVEMENTS_SERVER_UNREACHABLE:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_NETWORK];
case MENU_SETTING_GROUP:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_SETTING];
case MENU_SET_SCREEN_BRIGHTNESS:
Expand Down
2 changes: 2 additions & 0 deletions menu/drivers/xmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3465,6 +3465,8 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
return xmb->textures.list[XMB_TEXTURE_RELOAD];
case MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS:
return xmb->textures.list[XMB_TEXTURE_PAUSE];
case MENU_ENUM_LABEL_ACHIEVEMENT_SERVER_UNREACHABLE:
return xmb->textures.list[XMB_TEXTURE_NETWORK];
case MENU_SET_SCREEN_BRIGHTNESS:
return xmb->textures.list[XMB_TEXTURE_BRIGHTNESS];
case MENU_SETTING_GROUP:
Expand Down
1 change: 1 addition & 0 deletions menu/menu_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ enum menu_settings_type
MENU_SETTING_HORIZONTAL_MENU,
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS,
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS,
MENU_INFO_ACHIEVEMENTS_SERVER_UNREACHABLE,
MENU_SETTING_PLAYLIST_MANAGER_DEFAULT_CORE,
MENU_SETTING_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE,
MENU_SETTING_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE,
Expand Down
3 changes: 3 additions & 0 deletions msg_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -2926,6 +2926,9 @@ enum msg_hash_enums
MENU_LABEL(ACHIEVEMENT_RESUME_CANCEL),
MENU_LABEL(ACHIEVEMENT_PAUSE),
MENU_LABEL(ACHIEVEMENT_RESUME),
MENU_LABEL(ACHIEVEMENT_SERVER_UNREACHABLE),
MENU_LABEL(CHEEVOS_SERVER_DISCONNECTED),
MENU_LABEL(CHEEVOS_SERVER_RECONNECTED),
MENU_LABEL(CORE_INFORMATION),
MENU_LABEL(DISC_INFORMATION),
MENU_LABEL(CORE_LOCK),
Expand Down

0 comments on commit 93e5566

Please sign in to comment.