Add launcher preferences and modular landing studio [skip ci]

This commit is contained in:
SCOPEDD committed 2026-09-30 06:48:03 -04:00
1 parent 454620f21e
commit 6deff62a3a
25 files changed
+822 -682

No files matched your search

+25 -9
View File
@@ -52,9 +52,12 @@ pub struct Bootstrap {
accounts: Vec<Account>,
active_account: Option<String>,
manifest: Option<LauncherManifest>,
game_running: Option<String>,
game_running: Vec<RunningGameInfo>,
}
#[derive(Serialize)]
struct RunningGameInfo { run_id: String, instance_id: String }
#[tauri::command]
pub fn bootstrap(state: State<'_, AppState>) -> Bootstrap {
let accounts = state.accounts.read().unwrap().clone();
@@ -74,7 +77,7 @@ pub fn bootstrap(state: State<'_, AppState>) -> Bootstrap {
accounts: accounts.accounts,
active_account: accounts.active,
manifest: state.manifest.read().unwrap().clone(),
game_running: state.game.lock().unwrap().as_ref().map(|g| g.instance_id.clone()),
game_running: state.game.lock().unwrap().iter().map(|g| RunningGameInfo { run_id: g.run_id.clone(), instance_id: g.instance_id.clone() }).collect(),
}
}
@@ -119,11 +122,24 @@ pub async fn set_panel_url(state: State<'_, AppState>, url: String) -> Res<Launc
pub fn save_settings(state: State<'_, AppState>, settings: Settings) -> Res<()> {
let mut current = state.settings.write().unwrap();
let panel = current.panel_url.clone();
*current = Settings { panel_url: panel, ..settings };
let captured = current.instance_game_options.clone();
*current = Settings { panel_url: panel, instance_game_options: captured, ..settings };
drop(current);
state.save_settings().map_err(aerr)
}
#[tauri::command]
pub fn save_instance_options(state: State<'_, AppState>, instance_id: String) -> Res<std::collections::BTreeMap<String, String>> {
if state.game.lock().unwrap().iter().any(|g| g.instance_id == instance_id) {
return Err("close this instance before saving its game settings".into());
}
let options = scopenet_core::options::read_vanilla_preferences(&state.layout.instance_dir(&instance_id)).map_err(aerr)?;
if options.is_empty() { return Err("no vanilla options.txt settings found yet".into()); }
state.settings.write().unwrap().instance_game_options.insert(instance_id, options.clone());
state.save_settings().map_err(aerr)?;
Ok(options)
}
// ---- accounts ----
#[tauri::command]
@@ -345,8 +361,8 @@ pub fn repair_instance(app: AppHandle, state: State<'_, AppState>, instance_id:
}
fn start_task(app: AppHandle, state: &AppState, instance_id: String, start: bool, deep: bool) -> Res<()> {
if state.game.lock().unwrap().is_some() {
return Err("Minecraft is already running".into());
if deep && state.game.lock().unwrap().iter().any(|g| g.instance_id == instance_id) {
return Err("Close this instance's game windows before repairing it".into());
}
let mut task = state.task.lock().unwrap();
if task.as_ref().is_some_and(|t| !t.is_finished()) {
@@ -373,9 +389,9 @@ pub fn cancel_launch(app: AppHandle, state: State<'_, AppState>, instance_id: St
}
#[tauri::command]
pub fn kill_game(state: State<'_, AppState>) {
if let Some(g) = state.game.lock().unwrap().take() {
g.kill.send(()).ok();
pub fn kill_game(state: State<'_, AppState>, run_id: String) {
if let Some(g) = state.game.lock().unwrap().iter_mut().find(|g| g.run_id == run_id) {
if let Some(kill) = g.kill.take() { kill.send(()).ok(); }
}
}
@@ -444,7 +460,7 @@ pub async fn storage_info(state: State<'_, AppState>) -> Res<Storage> {
#[tauri::command]
pub async fn delete_instance_data(state: State<'_, AppState>, instance_id: String) -> Res<()> {
if state.game.lock().unwrap().as_ref().is_some_and(|g| g.instance_id == instance_id) {
if state.game.lock().unwrap().iter().any(|g| g.instance_id == instance_id) {
return Err("close the game first".into());
}
let dir = state.layout.instance_dir(&instance_id);