From fba51d78b815b1fc50c23b5941bcdb141ddb57ab Mon Sep 17 00:00:00 2001 From: Kr4ight Date: Mon, 6 Apr 2026 21:13:02 +0200 Subject: [PATCH] Working Instance Sync --- src-tauri/src/features/instance_sync.rs | 73 +++++++++++++++++++++++-- src-tauri/src/features/mod.rs | 15 +++++ src-tauri/src/lib.rs | 8 ++- 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/features/instance_sync.rs b/src-tauri/src/features/instance_sync.rs index f597f98..1949e78 100644 --- a/src-tauri/src/features/instance_sync.rs +++ b/src-tauri/src/features/instance_sync.rs @@ -1,9 +1,9 @@ -use std::collections::HashMap; +use std::{collections::HashMap, fs, path::PathBuf}; use lyceris::auth::microsoft::MinecraftAccount; use tauri::State; -use crate::{features::Feature, GameVersion, SharedState}; +use crate::{features::Feature, launcher::launcher_dir, GameVersion, SharedState}; pub struct InstanceSync {} @@ -20,7 +20,7 @@ impl Feature for InstanceSync { version: &GameVersion, account: &MinecraftAccount, ) -> super::FeatureResult { - println!("Launching {} for {}", version.id, account.username); + sync_to_instance(version).map_err(|e| e.to_string())?; Ok(()) } @@ -31,12 +31,70 @@ impl Feature for InstanceSync { version: &GameVersion, account: &MinecraftAccount, ) -> super::FeatureResult { - println!("Game launched!"); + sync_back_from_instance(version).map_err(|e| e.to_string())?; Ok(()) } } +fn sync_to_instance(version: &GameVersion) -> std::io::Result<()> { + let global_path = options_path_global(); + let instance_path = options_path_instance(version); + + if !global_path.exists() { + if let Ok(instance_content) = fs::read_to_string(instance_path) { + fs::write(global_path, instance_content)?; + } + + return Ok(()); + } + + let global_content = fs::read_to_string(global_path)?; + + // Ensure instance dir exists + if let Some(parent) = instance_path.parent() { + fs::create_dir_all(parent)?; + } + + fs::write(instance_path, global_content)?; + + Ok(()) +} + +fn sync_back_from_instance(version: &GameVersion) -> std::io::Result<()> { + let global_path = options_path_global(); + let instance_path = options_path_instance(version); + + let global_content = fs::read_to_string(&global_path)?; + let instance_content = fs::read_to_string(&instance_path)?; + + let mut global_map = parse_options(&global_content); + let instance_map = parse_options(&instance_content); + + // Only apply changes (ignore deletions) + for (key, instance_value) in instance_map { + match global_map.get(&key) { + Some(global_value) if global_value == &instance_value => {} + _ => { + // changed or new → update global + global_map.insert(key, instance_value); + } + } + } + + fs::write(global_path, serialize_options(&global_map))?; + + Ok(()) +} + +fn options_path_global() -> PathBuf { + launcher_dir().join("options.txt") +} + +fn options_path_instance(version: &GameVersion) -> PathBuf { + launcher_dir().join(&version.id).join("options.txt") +} + fn parse_options(content: &str) -> HashMap { let mut map = HashMap::new(); @@ -52,3 +110,10 @@ fn parse_options(content: &str) -> HashMap { map } + +fn serialize_options(map: &HashMap) -> String { + map.iter() + .map(|(k, v)| format!("{k}:{v}")) + .collect::>() + .join("\n") +} diff --git a/src-tauri/src/features/mod.rs b/src-tauri/src/features/mod.rs index 76962ee..b4afedf 100644 --- a/src-tauri/src/features/mod.rs +++ b/src-tauri/src/features/mod.rs @@ -1,4 +1,5 @@ use lyceris::auth::microsoft::MinecraftAccount; +use serde::{Deserialize, Serialize}; use tauri::State; use tokio::sync::Mutex; @@ -8,6 +9,20 @@ mod instance_sync; pub type FeatureResult = Result<(), String>; +#[derive(Clone, Serialize, Deserialize)] +pub struct FeatureSettings { + // Instance Sync + sync_options: bool, +} + +impl Default for FeatureSettings { + fn default() -> Self { + Self { + sync_options: false, + } + } +} + #[allow(unused_variables)] pub trait Feature: Send + Sync { fn launch( diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c286f72..c6ed123 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -9,7 +9,7 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::launcher::launcher_dir; +use crate::{features::FeatureSettings, launcher::launcher_dir}; pub type SharedState = Arc>; @@ -36,6 +36,7 @@ pub struct GameVersion { #[derive(Clone, Serialize, Deserialize)] pub struct LauncherSettings { pub max_memory: u32, + pub features: FeatureSettings, } // --- App State --- @@ -48,7 +49,10 @@ pub struct AppState { impl Default for AppState { fn default() -> Self { Self { - settings: LauncherSettings { max_memory: 4096 }, + settings: LauncherSettings { + max_memory: 4096, + features: FeatureSettings::default(), + }, version: String::from("1.21.6"), } }