leaderboard tracker (#740)
* leaderboard tracker * more * more * more * more
This commit is contained in:
parent
c4b86eb4b1
commit
595089187d
@ -7,6 +7,7 @@
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
using namespace Vulkan;
|
||||
|
||||
@ -101,6 +102,8 @@ static TTF_Font *achievement_challenge_indicator_font;
|
||||
static std::vector<const char *> achievement_challenge_indicators;
|
||||
static Vulkan::ImageHandle achievement_challenge_indicator_image;
|
||||
static Vulkan::ImageHandle achievement_progress_indicator_image;
|
||||
static std::map<uint32_t, std::string> leaderboard_trackers;
|
||||
static Vulkan::ImageHandle leaderboard_tracker_image;
|
||||
|
||||
#define MESSAGE_TIME 3000 // 3 seconds
|
||||
|
||||
@ -308,12 +311,15 @@ void rdp_init(void *_window, GFX_INFO _gfx_info, const void *font,
|
||||
achievement_challenge_indicators.clear();
|
||||
achievement_challenge_indicator_image = Vulkan::ImageHandle();
|
||||
achievement_progress_indicator_image = Vulkan::ImageHandle();
|
||||
leaderboard_trackers.clear();
|
||||
leaderboard_tracker_image = Vulkan::ImageHandle();
|
||||
}
|
||||
|
||||
void rdp_close() {
|
||||
messages = std::queue<Message>();
|
||||
achievement_challenge_indicator_image = Vulkan::ImageHandle();
|
||||
achievement_progress_indicator_image = Vulkan::ImageHandle();
|
||||
leaderboard_tracker_image = Vulkan::ImageHandle();
|
||||
|
||||
if (wsi)
|
||||
wsi->end_frame();
|
||||
@ -490,6 +496,8 @@ static void render_frame(Vulkan::Device &device) {
|
||||
}
|
||||
} else if (achievement_progress_indicator_image) {
|
||||
draw_indicator(cmd, achievement_progress_indicator_image, vp);
|
||||
} else if (leaderboard_tracker_image) {
|
||||
draw_indicator(cmd, leaderboard_tracker_image, vp);
|
||||
} else if (achievement_challenge_indicator_image) {
|
||||
draw_indicator(cmd, achievement_challenge_indicator_image, vp);
|
||||
}
|
||||
@ -794,8 +802,9 @@ uint64_t rdp_process_commands() {
|
||||
|
||||
static void update_challenge_indicator() {
|
||||
std::string message;
|
||||
for (const auto &achievement_title : achievement_challenge_indicators) {
|
||||
message += achievement_title;
|
||||
const auto &v = achievement_challenge_indicators;
|
||||
for (size_t i = 0; i < std::min<size_t>(v.size(), 5); ++i) {
|
||||
message += v[i];
|
||||
message += '\n';
|
||||
}
|
||||
achievement_challenge_indicator_image = create_message_image(
|
||||
@ -803,6 +812,16 @@ static void update_challenge_indicator() {
|
||||
message.c_str());
|
||||
}
|
||||
|
||||
static void update_leaderboard_tracker() {
|
||||
std::string message;
|
||||
for (const auto &leaderboard_tracker : leaderboard_trackers) {
|
||||
message += leaderboard_tracker.second;
|
||||
message += '\n';
|
||||
}
|
||||
leaderboard_tracker_image =
|
||||
create_message_image(wsi->get_device(), 0, message_font, message.c_str());
|
||||
}
|
||||
|
||||
void achievement_challenge_indicator_add(const char *achievement_title) {
|
||||
achievement_challenge_indicators.push_back(achievement_title);
|
||||
update_challenge_indicator();
|
||||
@ -828,3 +847,18 @@ void achievement_progress_add(const char *achievement_title,
|
||||
void achievement_progress_remove(const char *achievement_title) {
|
||||
achievement_progress_indicator_image = Vulkan::ImageHandle();
|
||||
}
|
||||
|
||||
void leaderboard_tracker_add(uint32_t id, const char *display) {
|
||||
std::string message = display;
|
||||
leaderboard_trackers[id] = message;
|
||||
update_leaderboard_tracker();
|
||||
}
|
||||
|
||||
void leaderboard_tracker_remove(uint32_t id) {
|
||||
leaderboard_trackers.erase(id);
|
||||
if (leaderboard_trackers.empty()) {
|
||||
leaderboard_tracker_image = Vulkan::ImageHandle();
|
||||
} else {
|
||||
update_leaderboard_tracker();
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,8 @@ void achievement_challenge_indicator_remove(const char *achievement_title);
|
||||
void achievement_progress_add(const char *achievement_title,
|
||||
const char *progress);
|
||||
void achievement_progress_remove(const char *achievement_title);
|
||||
void leaderboard_tracker_add(uint32_t id, const char *display);
|
||||
void leaderboard_tracker_remove(uint32_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ static size_t g_dmem_size = 0;
|
||||
static bool g_game_loaded = false;
|
||||
static bool g_user_logged_in = false;
|
||||
static bool g_challenge = false;
|
||||
static bool g_leaderboard = false;
|
||||
static const char *g_username = NULL;
|
||||
static const char *g_token = NULL;
|
||||
static char load_game_error_message[512];
|
||||
@ -181,7 +182,7 @@ void ra_set_dmem(const uint8_t *dmem, size_t dmem_size) {
|
||||
static void leaderboard_started(const rc_client_leaderboard_t *leaderboard) {
|
||||
char buffer[512];
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "Lboard attempt started: %s",
|
||||
snprintf(buffer, sizeof(buffer), "Leaderboard started: %s",
|
||||
leaderboard->title);
|
||||
rdp_onscreen_message(buffer);
|
||||
}
|
||||
@ -189,7 +190,7 @@ static void leaderboard_started(const rc_client_leaderboard_t *leaderboard) {
|
||||
static void leaderboard_failed(const rc_client_leaderboard_t *leaderboard) {
|
||||
char buffer[512];
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "Lboard attempt failed: %s",
|
||||
snprintf(buffer, sizeof(buffer), "Leaderboard failed: %s",
|
||||
leaderboard->title);
|
||||
rdp_onscreen_message(buffer);
|
||||
}
|
||||
@ -197,7 +198,7 @@ static void leaderboard_failed(const rc_client_leaderboard_t *leaderboard) {
|
||||
static void leaderboard_submitted(const rc_client_leaderboard_t *leaderboard) {
|
||||
char buffer[512];
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "Lboard submitted: %s - %s",
|
||||
snprintf(buffer, sizeof(buffer), "Leaderboard submitted: %s - %s",
|
||||
leaderboard->title, leaderboard->tracker_value);
|
||||
rdp_onscreen_message(buffer);
|
||||
}
|
||||
@ -243,13 +244,16 @@ static void event_handler(const rc_client_event_t *event, rc_client_t *client) {
|
||||
achievement_triggered(event->achievement);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_STARTED:
|
||||
leaderboard_started(event->leaderboard);
|
||||
if (g_leaderboard)
|
||||
leaderboard_started(event->leaderboard);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_FAILED:
|
||||
leaderboard_failed(event->leaderboard);
|
||||
if (g_leaderboard)
|
||||
leaderboard_failed(event->leaderboard);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED:
|
||||
leaderboard_submitted(event->leaderboard);
|
||||
if (g_leaderboard)
|
||||
leaderboard_submitted(event->leaderboard);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW:
|
||||
if (g_challenge)
|
||||
@ -271,10 +275,18 @@ static void event_handler(const rc_client_event_t *event, rc_client_t *client) {
|
||||
event->achievement->measured_progress);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW:
|
||||
if (g_leaderboard)
|
||||
leaderboard_tracker_add(event->leaderboard_tracker->id,
|
||||
event->leaderboard_tracker->display);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE:
|
||||
if (g_leaderboard)
|
||||
leaderboard_tracker_remove(event->leaderboard_tracker->id);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE:
|
||||
if (g_leaderboard)
|
||||
leaderboard_tracker_add(event->leaderboard_tracker->id,
|
||||
event->leaderboard_tracker->display);
|
||||
break;
|
||||
case RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD:
|
||||
break;
|
||||
@ -293,7 +305,7 @@ static void event_handler(const rc_client_event_t *event, rc_client_t *client) {
|
||||
}
|
||||
}
|
||||
|
||||
void ra_init_client(bool hardcore, bool challenge) {
|
||||
void ra_init_client(bool hardcore, bool challenge, bool leaderboard) {
|
||||
// Create the client instance (using a global variable simplifies this
|
||||
// example)
|
||||
g_client = rc_client_create(read_memory, server_call);
|
||||
@ -311,6 +323,7 @@ void ra_init_client(bool hardcore, bool challenge) {
|
||||
rc_client_set_hardcore_enabled(g_client, hardcore);
|
||||
|
||||
g_challenge = challenge;
|
||||
g_leaderboard = leaderboard;
|
||||
}
|
||||
|
||||
bool ra_get_hardcore() {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void ra_init_client(bool hardcore, bool challenge);
|
||||
void ra_init_client(bool hardcore, bool challenge, bool leaderboard);
|
||||
void ra_shutdown_client();
|
||||
void ra_welcome();
|
||||
bool ra_get_hardcore();
|
||||
|
||||
@ -128,10 +128,10 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
|
||||
cheats::execute_cheats(device, device.cheats.cheats.clone());
|
||||
}
|
||||
|
||||
retroachievements::do_frame();
|
||||
|
||||
ui::video::render_frame();
|
||||
|
||||
retroachievements::do_frame();
|
||||
|
||||
let (mut speed_limiter_toggled, paused) = ui::video::check_callback(device);
|
||||
|
||||
if let Some(netplay) = &mut device.netplay {
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@ -111,6 +111,11 @@ struct Args {
|
||||
help = "Enable Challenge Indicators for RetroAchievements"
|
||||
)]
|
||||
ra_challenge: bool,
|
||||
#[arg(
|
||||
long = "ra-leaderboard",
|
||||
help = "Enable Leaderboard Trackers for RetroAchievements"
|
||||
)]
|
||||
ra_leaderboard: bool,
|
||||
}
|
||||
|
||||
#[tokio::main(worker_threads = 4)]
|
||||
@ -164,9 +169,13 @@ async fn main() -> std::io::Result<()> {
|
||||
};
|
||||
|
||||
if cfg!(ra_hardcore_enabled) {
|
||||
retroachievements::init_client(args.ra_hardcore, args.ra_challenge);
|
||||
retroachievements::init_client(
|
||||
args.ra_hardcore,
|
||||
args.ra_challenge,
|
||||
args.ra_leaderboard,
|
||||
);
|
||||
} else {
|
||||
retroachievements::init_client(false, args.ra_challenge);
|
||||
retroachievements::init_client(false, args.ra_challenge, args.ra_leaderboard);
|
||||
}
|
||||
let mut shutdown_tx = None;
|
||||
|
||||
@ -264,7 +273,7 @@ async fn main() -> std::io::Result<()> {
|
||||
ui::input::bind_input_profile(&mut ui, profile, port);
|
||||
}
|
||||
} else {
|
||||
retroachievements::init_client(false, false);
|
||||
retroachievements::init_client(false, false, false);
|
||||
gui::app_window();
|
||||
retroachievements::shutdown_client();
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ pub struct RAConfig {
|
||||
pub enabled: bool,
|
||||
pub hardcore: bool,
|
||||
pub challenge: bool,
|
||||
pub leaderboard: bool,
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@ -41,6 +42,7 @@ pub extern "C" fn store_retroachievements_credentials(
|
||||
enabled: result.enabled,
|
||||
hardcore: result.hardcore,
|
||||
challenge: result.challenge,
|
||||
leaderboard: result.leaderboard,
|
||||
}
|
||||
} else {
|
||||
RAConfig {
|
||||
@ -49,6 +51,7 @@ pub extern "C" fn store_retroachievements_credentials(
|
||||
enabled: false,
|
||||
hardcore: false,
|
||||
challenge: false,
|
||||
leaderboard: false,
|
||||
}
|
||||
};
|
||||
let f = std::fs::File::create(&file_path).unwrap();
|
||||
@ -170,6 +173,7 @@ pub fn ra_window(app: &ui::gui::AppWindow) {
|
||||
app.set_ra_enabled(result.enabled);
|
||||
app.set_ra_hardcore(result.hardcore);
|
||||
app.set_ra_challenge(result.challenge);
|
||||
app.set_ra_leaderboard(result.leaderboard);
|
||||
token = result.token;
|
||||
} else {
|
||||
app.set_ra_hardcore(true);
|
||||
@ -199,7 +203,7 @@ pub fn ra_window(app: &ui::gui::AppWindow) {
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
app.on_ra_toggled(move |enabled, hardcore, challenge| {
|
||||
app.on_ra_toggled(move |enabled, hardcore, challenge, leaderboard| {
|
||||
let file_path = ui::get_dirs().config_dir.join("retroachievements.json");
|
||||
let raconfig = if let Ok(ra_config) = std::fs::read(&file_path)
|
||||
&& let Ok(result) = serde_json::from_slice::<RAConfig>(ra_config.as_ref())
|
||||
@ -212,6 +216,7 @@ pub fn ra_window(app: &ui::gui::AppWindow) {
|
||||
enabled,
|
||||
hardcore,
|
||||
challenge,
|
||||
leaderboard,
|
||||
}
|
||||
} else {
|
||||
RAConfig {
|
||||
@ -220,6 +225,7 @@ pub fn ra_window(app: &ui::gui::AppWindow) {
|
||||
enabled,
|
||||
hardcore,
|
||||
challenge,
|
||||
leaderboard,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -229,6 +235,7 @@ pub fn ra_window(app: &ui::gui::AppWindow) {
|
||||
enabled,
|
||||
hardcore,
|
||||
challenge,
|
||||
leaderboard,
|
||||
}
|
||||
};
|
||||
let f = std::fs::File::create(&file_path).unwrap();
|
||||
@ -269,8 +276,8 @@ pub fn do_idle() {
|
||||
unsafe { ra_do_idle() };
|
||||
}
|
||||
|
||||
pub fn init_client(hardcore: bool, challenge: bool) {
|
||||
unsafe { ra_init_client(hardcore, challenge) };
|
||||
pub fn init_client(hardcore: bool, challenge: bool, leaderboard: bool) {
|
||||
unsafe { ra_init_client(hardcore, challenge, leaderboard) };
|
||||
}
|
||||
|
||||
pub fn shutdown_client() {
|
||||
|
||||
@ -34,6 +34,7 @@ pub struct GameSettings {
|
||||
pub struct RASettings {
|
||||
pub hardcore: bool,
|
||||
pub challenge: bool,
|
||||
pub leaderboard: bool,
|
||||
}
|
||||
|
||||
fn check_latest_version(weak: slint::Weak<AppWindow>) {
|
||||
@ -370,6 +371,9 @@ pub fn run_rom(
|
||||
if ra_settings.challenge {
|
||||
command.args(["--ra-challenge"]);
|
||||
}
|
||||
if ra_settings.leaderboard {
|
||||
command.args(["--ra-leaderboard"]);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..4 {
|
||||
@ -434,6 +438,7 @@ fn open_rom(app: &AppWindow) {
|
||||
let disable_expansion_pak = app.get_disable_expansion_pak();
|
||||
let ra_hardcore = app.get_ra_hardcore();
|
||||
let ra_challenge = app.get_ra_challenge();
|
||||
let ra_leaderboard = app.get_ra_leaderboard();
|
||||
|
||||
let weak = app.as_weak();
|
||||
tokio::spawn(async move {
|
||||
@ -467,6 +472,7 @@ fn open_rom(app: &AppWindow) {
|
||||
RASettings {
|
||||
hardcore: ra_hardcore,
|
||||
challenge: ra_challenge,
|
||||
leaderboard: ra_leaderboard,
|
||||
},
|
||||
weak,
|
||||
);
|
||||
|
||||
@ -38,7 +38,7 @@ export component AppWindow inherits Window {
|
||||
callback ra_button_clicked(string);
|
||||
callback ra_games_clicked;
|
||||
callback ra_show_profile_clicked(string);
|
||||
callback ra_toggled(bool,bool,bool);
|
||||
callback ra_toggled(bool,bool,bool,bool);
|
||||
in property version <=> AboutData.version;
|
||||
in property has_update <=> AboutData.has_update;
|
||||
in-out property ra_username <=> RAData.ra_username;
|
||||
@ -49,6 +49,7 @@ export component AppWindow inherits Window {
|
||||
in-out property ra_enabled <=> RAData.enabled;
|
||||
in-out property ra_hardcore <=> RAData.hardcore;
|
||||
in-out property ra_challenge <=> RAData.challenge;
|
||||
in-out property ra_leaderboard <=> RAData.leaderboard;
|
||||
in-out property integer_scaling <=> SettingsData.integer_scaling;
|
||||
in-out property fullscreen <=> SettingsData.fullscreen;
|
||||
in-out property widescreen <=> SettingsData.widescreen;
|
||||
@ -135,8 +136,8 @@ export component AppWindow inherits Window {
|
||||
ra_button_clicked(password) => {
|
||||
ra_button_clicked(password);
|
||||
}
|
||||
ra_toggled(enabled,hardcore,challenge) => {
|
||||
ra_toggled(enabled,hardcore,challenge);
|
||||
ra_toggled(enabled,hardcore,challenge,leaderboard) => {
|
||||
ra_toggled(enabled,hardcore,challenge,leaderboard);
|
||||
}
|
||||
ra_games_clicked => {
|
||||
ra_games_clicked();
|
||||
|
||||
@ -8,6 +8,7 @@ export global RAData {
|
||||
in-out property <bool> enabled;
|
||||
in-out property <bool> hardcore;
|
||||
in-out property <bool> challenge;
|
||||
in-out property <bool> leaderboard;
|
||||
in-out property <bool> ra_logging_in;
|
||||
in-out property <bool> ra_show_profile;
|
||||
in-out property <string> ra_username;
|
||||
@ -17,7 +18,7 @@ export global RAData {
|
||||
|
||||
export component RetroAchievements inherits Page {
|
||||
callback ra_button_clicked(string);
|
||||
callback ra_toggled(bool,bool,bool);
|
||||
callback ra_toggled(bool,bool,bool,bool);
|
||||
callback ra_games_clicked;
|
||||
callback ra_show_profile_clicked(string);
|
||||
title: @tr("RetroAchievements");
|
||||
@ -38,7 +39,7 @@ export component RetroAchievements inherits Page {
|
||||
RAData.current_user_message = "Not currently logged in";
|
||||
RAData.ra_show_profile = false;
|
||||
}
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge);
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge,RAData.leaderboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,7 +51,7 @@ export component RetroAchievements inherits Page {
|
||||
enabled: RAData.enabled;
|
||||
toggled => {
|
||||
RAData.hardcore = self.checked;
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge);
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge,RAData.leaderboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,7 +63,19 @@ export component RetroAchievements inherits Page {
|
||||
enabled: RAData.enabled;
|
||||
toggled => {
|
||||
RAData.challenge = self.checked;
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge);
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge,RAData.leaderboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalBox {
|
||||
alignment: center;
|
||||
CheckBox {
|
||||
text: @tr("Leaderboard Trackers");
|
||||
checked: RAData.leaderboard;
|
||||
enabled: RAData.enabled;
|
||||
toggled => {
|
||||
RAData.leaderboard = self.checked;
|
||||
ra_toggled(RAData.enabled,RAData.hardcore,RAData.challenge,RAData.leaderboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1110,6 +1110,7 @@ fn setup_wait_window(
|
||||
RASettings {
|
||||
hardcore: false,
|
||||
challenge: false,
|
||||
leaderboard: false,
|
||||
},
|
||||
weak_app,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user