Working Instance Sync

This commit is contained in:
Kr4ight
2026-04-06 21:13:02 +02:00
parent 950d7f0a1d
commit fba51d78b8
3 changed files with 90 additions and 6 deletions
+69 -4
View File
@@ -1,9 +1,9 @@
use std::collections::HashMap; use std::{collections::HashMap, fs, path::PathBuf};
use lyceris::auth::microsoft::MinecraftAccount; use lyceris::auth::microsoft::MinecraftAccount;
use tauri::State; use tauri::State;
use crate::{features::Feature, GameVersion, SharedState}; use crate::{features::Feature, launcher::launcher_dir, GameVersion, SharedState};
pub struct InstanceSync {} pub struct InstanceSync {}
@@ -20,7 +20,7 @@ impl Feature for InstanceSync {
version: &GameVersion, version: &GameVersion,
account: &MinecraftAccount, account: &MinecraftAccount,
) -> super::FeatureResult { ) -> super::FeatureResult {
println!("Launching {} for {}", version.id, account.username); sync_to_instance(version).map_err(|e| e.to_string())?;
Ok(()) Ok(())
} }
@@ -31,12 +31,70 @@ impl Feature for InstanceSync {
version: &GameVersion, version: &GameVersion,
account: &MinecraftAccount, account: &MinecraftAccount,
) -> super::FeatureResult { ) -> super::FeatureResult {
println!("Game launched!"); sync_back_from_instance(version).map_err(|e| e.to_string())?;
Ok(()) 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<String, String> { fn parse_options(content: &str) -> HashMap<String, String> {
let mut map = HashMap::new(); let mut map = HashMap::new();
@@ -52,3 +110,10 @@ fn parse_options(content: &str) -> HashMap<String, String> {
map map
} }
fn serialize_options(map: &HashMap<String, String>) -> String {
map.iter()
.map(|(k, v)| format!("{k}:{v}"))
.collect::<Vec<_>>()
.join("\n")
}
+15
View File
@@ -1,4 +1,5 @@
use lyceris::auth::microsoft::MinecraftAccount; use lyceris::auth::microsoft::MinecraftAccount;
use serde::{Deserialize, Serialize};
use tauri::State; use tauri::State;
use tokio::sync::Mutex; use tokio::sync::Mutex;
@@ -8,6 +9,20 @@ mod instance_sync;
pub type FeatureResult = Result<(), String>; 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)] #[allow(unused_variables)]
pub trait Feature: Send + Sync { pub trait Feature: Send + Sync {
fn launch( fn launch(
+6 -2
View File
@@ -9,7 +9,7 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use crate::launcher::launcher_dir; use crate::{features::FeatureSettings, launcher::launcher_dir};
pub type SharedState = Arc<Mutex<AppState>>; pub type SharedState = Arc<Mutex<AppState>>;
@@ -36,6 +36,7 @@ pub struct GameVersion {
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
pub struct LauncherSettings { pub struct LauncherSettings {
pub max_memory: u32, pub max_memory: u32,
pub features: FeatureSettings,
} }
// --- App State --- // --- App State ---
@@ -48,7 +49,10 @@ pub struct AppState {
impl Default for AppState { impl Default for AppState {
fn default() -> Self { fn default() -> Self {
Self { Self {
settings: LauncherSettings { max_memory: 4096 }, settings: LauncherSettings {
max_memory: 4096,
features: FeatureSettings::default(),
},
version: String::from("1.21.6"), version: String::from("1.21.6"),
} }
} }