read RA settings from CLI (#913)

* read RA settings from CLI

* more
This commit is contained in:
Logan McNaughton
2026-05-19 09:20:08 +02:00
committed by GitHub
parent 41e66825d0
commit 9f2cfb5a9f
7 changed files with 28 additions and 142 deletions
+1 -2
View File
@@ -180,8 +180,7 @@ fn main() {
if cfg!(feature = "gui") {
retroachievements_builder = retroachievements_builder
.allowlist_function("ra_logout_user")
.allowlist_function("ra_get_username")
.allowlist_function("ra_get_token");
.allowlist_function("ra_get_username");
}
let retroachievements_bindings = retroachievements_builder
-4
View File
@@ -86,10 +86,6 @@ const char *ra_get_username() {
const rc_client_user_t *user = rc_client_get_user_info(g_client);
return user ? user->username : NULL;
}
const char *ra_get_token() {
const rc_client_user_t *user = rc_client_get_user_info(g_client);
return user ? user->token : NULL;
}
void ra_logout_user() { rc_client_logout(g_client); }
-1
View File
@@ -18,7 +18,6 @@ void ra_login_user(const char *username, const char *password, void *userdata);
void ra_login_token_user(const char *username, const char *token,
void *userdata);
const char *ra_get_username();
const char *ra_get_token();
size_t ra_state_size();
void ra_save_state(uint8_t *state, size_t state_size);
void ra_load_state(const uint8_t *state, size_t state_size);
+24 -37
View File
@@ -80,43 +80,19 @@ struct Args {
help = "Username for RetroAchievements"
)]
ra_username: Option<String>,
#[arg(
long = "ra-token",
value_name = "TOKEN",
help = "Token for RetroAchievements",
hide = true
)]
ra_token: Option<String>,
#[arg(
long = "ra-password",
value_name = "PASSWORD",
help = "Password for RetroAchievements"
)]
ra_password: Option<String>,
#[arg(
long = "ra-hardcore",
help = "Enable Hardcore mode for RetroAchievements"
)]
ra_hardcore: bool,
#[arg(
long = "ra-challenge",
help = "Enable Challenge Indicators for RetroAchievements"
)]
ra_challenge: bool,
#[arg(
long = "ra-leaderboard",
help = "Enable Leaderboard Trackers for RetroAchievements"
)]
ra_leaderboard: bool,
#[arg(long = "discord-rich-presence", help = "Enable Discord Rich Presence")]
discord_rich_presence: bool,
}
pub async fn run() -> std::io::Result<()> {
let dirs = ui::get_dirs();
std::fs::create_dir_all(dirs.config_dir)?;
std::fs::create_dir_all(dirs.cache_dir)?;
std::fs::create_dir_all(&dirs.config_dir)?;
std::fs::create_dir_all(&dirs.cache_dir)?;
std::fs::create_dir_all(dirs.data_dir.join("saves"))?;
std::fs::create_dir_all(dirs.data_dir.join("states"))?;
@@ -176,10 +152,11 @@ pub async fn run() -> std::io::Result<()> {
let mut shutdown_tx = None;
let mut usb_handle = None;
if let Some(peer_addr) = args.netplay_peer_addr
let rich_presence = if let Some(peer_addr) = args.netplay_peer_addr
&& let Some(player_number) = args.netplay_player_number
{
device.netplay = Some(netplay::init(peer_addr.parse().unwrap(), player_number));
false
} else {
for i in 0..4 {
if device.ui.config.input.transfer_pak[i]
@@ -196,29 +173,39 @@ pub async fn run() -> std::io::Result<()> {
(shutdown_tx, usb_handle, device.ui.usb) = ui::usb::init();
}
if let Some(username) = args.ra_username {
let file_path = dirs.config_dir.join("retroachievements.json");
if let ra_config = std::fs::read(&file_path).unwrap_or_default()
&& let ra_config =
serde_json::from_slice::<retroachievements::RAConfig>(ra_config.as_ref())
.unwrap_or_default()
&& (ra_config.enabled || args.ra_username.is_some())
{
let username = args.ra_username.unwrap_or(ra_config.username);
retroachievements::init_client(
if cfg!(ra_hardcore_enabled) {
args.ra_hardcore
ra_config.hardcore
} else {
false
},
args.ra_challenge,
args.ra_leaderboard,
ra_config.challenge,
ra_config.leaderboard,
);
let (tx, rx) = tokio::sync::oneshot::channel::<bool>();
if let Some(password) = args.ra_password {
retroachievements::login_user(username, password, tx);
} else if let Some(token) = args.ra_token {
retroachievements::login_token_user(username, token, tx);
} else if !ra_config.token.is_empty() {
retroachievements::login_token_user(username, ra_config.token, tx);
} else {
tx.send(false).unwrap();
}
rx.await.unwrap();
ra_config.rich_presence
} else {
false
}
}
};
device::run_game(
&mut device,
@@ -229,7 +216,7 @@ pub async fn run() -> std::io::Result<()> {
cheats,
load_savestate_slot: args.load_state,
},
args.discord_rich_presence,
rich_presence,
)
.await;
@@ -325,8 +312,8 @@ async fn android_main(app: slint::android::AndroidApp) {
let dirs = ui::get_dirs();
std::fs::create_dir_all(dirs.config_dir).unwrap();
std::fs::create_dir_all(dirs.cache_dir).unwrap();
std::fs::create_dir_all(&dirs.config_dir).unwrap();
std::fs::create_dir_all(&dirs.cache_dir).unwrap();
std::fs::create_dir_all(dirs.data_dir.join("saves")).unwrap();
std::fs::create_dir_all(dirs.data_dir.join("states")).unwrap();
+1 -16
View File
@@ -4,7 +4,7 @@ use crate::ui;
use discord_rich_presence::DiscordIpc;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(serde::Serialize, serde::Deserialize, Default)]
pub struct RAConfig {
pub username: String,
pub token: String,
@@ -266,21 +266,6 @@ pub fn get_username() -> Option<String> {
}
}
#[cfg(feature = "gui")]
pub fn get_token() -> Option<String> {
let c_token = unsafe { ra_get_token() };
if c_token.is_null() {
None
} else {
Some(
unsafe { std::ffi::CStr::from_ptr(c_token) }
.to_str()
.unwrap()
.to_string(),
)
}
}
pub fn state_size() -> usize {
unsafe { ra_state_size() }
}
-50
View File
@@ -1,4 +1,3 @@
use crate::retroachievements;
use crate::ui;
use slint::Model;
#[cfg(not(target_os = "android"))]
@@ -21,15 +20,6 @@ pub struct NetplayDevice {
pub player_number: u8,
}
#[derive(Clone)]
pub struct RASettings {
pub enabled: bool,
pub hardcore: bool,
pub challenge: bool,
pub leaderboard: bool,
pub rich_presence: bool,
}
fn check_latest_version(weak: slint::Weak<AppWindow>) {
let task = ui::WEB_CLIENT
.get("https://api.github.com/repos/gopher64/gopher64/releases/latest")
@@ -73,13 +63,6 @@ fn run_with_path(weak: slint::Weak<AppWindow>, path: std::path::PathBuf) {
load_savestate_slot: None,
},
None,
RASettings {
enabled: handle.get_ra_enabled(),
hardcore: handle.get_ra_hardcore(),
challenge: handle.get_ra_challenge(),
leaderboard: handle.get_ra_leaderboard(),
rich_presence: handle.get_ra_rich_presence(),
},
weak2,
);
})
@@ -550,7 +533,6 @@ pub fn run_rom(
file_path: std::path::PathBuf,
game_settings: ui::GameSettings,
netplay: Option<NetplayDevice>,
ra_settings: RASettings,
weak: slint::Weak<AppWindow>,
) {
tokio::spawn(async move {
@@ -588,26 +570,6 @@ pub fn run_rom(
cheats_path.to_str().unwrap(),
]);
}
if ra_settings.enabled {
command.args([
"--ra-username",
&retroachievements::get_username().unwrap_or("unknown".into()),
"--ra-token",
&retroachievements::get_token().unwrap_or("unknown".into()),
]);
if ra_settings.hardcore {
command.args(["--ra-hardcore"]);
}
if ra_settings.challenge {
command.args(["--ra-challenge"]);
}
if ra_settings.leaderboard {
command.args(["--ra-leaderboard"]);
}
if ra_settings.rich_presence {
command.args(["--discord-rich-presence"]);
}
}
let success = command
.arg(file_path.to_str().unwrap())
@@ -663,11 +625,6 @@ fn open_rom(app: &AppWindow) {
let overclock = app.get_overclock_n64_cpu();
let disable_expansion_pak = app.get_disable_expansion_pak();
let ra_enabled = app.get_ra_enabled();
let ra_hardcore = app.get_ra_hardcore();
let ra_challenge = app.get_ra_challenge();
let ra_leaderboard = app.get_ra_leaderboard();
let ra_rich_presence = app.get_ra_rich_presence();
let weak = app.as_weak();
tokio::spawn(async move {
@@ -681,13 +638,6 @@ fn open_rom(app: &AppWindow) {
load_savestate_slot: None,
},
None,
RASettings {
enabled: ra_enabled,
hardcore: ra_hardcore,
challenge: ra_challenge,
leaderboard: ra_leaderboard,
rich_presence: ra_rich_presence,
},
weak,
);
}
+2 -32
View File
@@ -3,7 +3,7 @@ use crate::device;
use crate::ui;
use crate::ui::gui::{
AppWindow, CustomNetplayServer, DispatcherDialog, ErrorDialog, NetplayCreate, NetplayDevice,
NetplayJoin, NetplayWait, RASettings, run_rom, save_settings,
NetplayJoin, NetplayWait, run_rom, save_settings,
};
use futures::{SinkExt, StreamExt};
use sha2::{Digest, Sha256};
@@ -266,7 +266,6 @@ fn show_custom_url_dialog(weak: slint::Weak<NetplayCreate>, server_url: slint::S
pub fn setup_create_window(
create_window: &NetplayCreate,
game_settings: ui::GameSettings,
ra_settings: RASettings,
rom_dir: slint::SharedString,
weak_app: slint::Weak<AppWindow>,
) {
@@ -326,7 +325,6 @@ pub fn setup_create_window(
let game_settings = game_settings.clone();
let weak = weak.clone();
let weak_app = weak_app.clone();
let ra_settings = ra_settings.clone();
tokio::spawn(async move {
let response = task.await;
weak_dialog
@@ -358,7 +356,6 @@ pub fn setup_create_window(
game_cheats.to_string(),
password.to_string(),
game_settings,
ra_settings,
weak_app,
weak.clone(),
);
@@ -388,7 +385,6 @@ pub fn setup_create_window(
game_cheats.to_string(),
password.to_string(),
game_settings.clone(),
ra_settings.clone(),
weak_app.clone(),
weak.clone(),
);
@@ -640,7 +636,6 @@ fn create_session(
game_cheats: String,
password: String,
game_settings: ui::GameSettings,
ra_settings: RASettings,
weak_app: slint::Weak<AppWindow>,
weak: slint::Weak<NetplayCreate>,
) {
@@ -739,7 +734,6 @@ fn create_session(
cheats: serde_json::from_str(cheats).unwrap(),
load_savestate_slot: None,
},
ra_settings,
handle.get_peer_addr(),
weak_app,
);
@@ -778,7 +772,6 @@ fn join_session(
game_hash: String,
password: String,
room_port: i32,
ra_settings: RASettings,
weak_app: slint::Weak<AppWindow>,
weak: slint::Weak<NetplayJoin>,
) {
@@ -866,7 +859,6 @@ fn join_session(
cheats: serde_json::from_str(cheats).unwrap(),
load_savestate_slot: None,
},
ra_settings,
handle.get_peer_addr(),
weak_app,
);
@@ -907,7 +899,6 @@ fn setup_wait_window(
player_name: slint::SharedString,
port: i32,
game_settings: ui::GameSettings,
ra_settings: RASettings,
peer_addr: slint::SharedString,
weak_app: slint::Weak<AppWindow>,
) {
@@ -1133,7 +1124,6 @@ fn setup_wait_window(
peer_addr: socket_addr,
player_number: player_number as u8,
}),
ra_settings,
weak_app,
);
handle.hide().unwrap();
@@ -1177,7 +1167,6 @@ fn setup_wait_window(
pub fn setup_join_window(
join_window: &NetplayJoin,
rom_dir: slint::SharedString,
ra_settings: RASettings,
weak_app: slint::Weak<AppWindow>,
) {
let (netplay_read_sender, netplay_read_receiver): (
@@ -1229,7 +1218,6 @@ pub fn setup_join_window(
game_hash.to_string(),
password.to_string(),
room_port,
ra_settings.clone(),
weak_app.clone(),
weak.clone(),
);
@@ -1256,13 +1244,6 @@ pub fn netplay_window(app: &AppWindow) {
cheats: std::collections::HashMap::new(), // not used here
load_savestate_slot: None,
},
RASettings {
enabled: handle.get_ra_enabled(),
hardcore: handle.get_ra_hardcore(),
challenge: handle.get_ra_challenge(),
leaderboard: handle.get_ra_leaderboard(),
rich_presence: handle.get_ra_rich_presence(),
},
handle.get_rom_dir(),
weak_app,
);
@@ -1278,18 +1259,7 @@ pub fn netplay_window(app: &AppWindow) {
.upgrade_in_event_loop(move |handle| {
let join_window = NetplayJoin::new().unwrap();
save_settings(&handle);
setup_join_window(
&join_window,
handle.get_rom_dir(),
RASettings {
enabled: handle.get_ra_enabled(),
hardcore: handle.get_ra_hardcore(),
challenge: handle.get_ra_challenge(),
leaderboard: handle.get_ra_leaderboard(),
rich_presence: handle.get_ra_rich_presence(),
},
weak_app,
);
setup_join_window(&join_window, handle.get_rom_dir(), weak_app);
})
.unwrap();
});