Implementing features

This commit is contained in:
Kr4ight
2026-04-06 19:50:56 +02:00
parent 1436950b90
commit 725ac2187f
5 changed files with 117 additions and 8 deletions
+51
View File
@@ -0,0 +1,51 @@
use std::collections::HashMap;
use lyceris::auth::microsoft::MinecraftAccount;
use crate::{features::Feature, GameVersion};
pub struct InstanceSync {}
impl Default for InstanceSync {
fn default() -> Self {
Self {}
}
}
impl Feature for InstanceSync {
fn launch(
&mut self,
version: &GameVersion,
account: &MinecraftAccount,
) -> super::FeatureResult {
println!("Launching {} for {}", version.id, account.username);
Ok(())
}
fn after_launch(
&mut self,
version: &GameVersion,
account: &MinecraftAccount,
) -> super::FeatureResult {
println!("Game launched!");
Ok(())
}
}
fn parse_options(content: &str) -> HashMap<String, String> {
let mut map = HashMap::new();
for line in content.lines() {
if line.trim().is_empty() {
continue;
}
if let Some((key, value)) = line.split_once(':') {
map.insert(key.to_string(), value.to_string());
}
}
map
}
+48
View File
@@ -0,0 +1,48 @@
use lyceris::auth::microsoft::MinecraftAccount;
use tokio::sync::Mutex;
use crate::{features::instance_sync::InstanceSync, GameVersion};
mod instance_sync;
pub type FeatureResult = Result<(), String>;
#[allow(unused_variables)]
pub trait Feature: Send + Sync {
fn launch(&mut self, version: &GameVersion, account: &MinecraftAccount) -> FeatureResult {
Ok(())
}
fn after_launch(&mut self, version: &GameVersion, account: &MinecraftAccount) -> FeatureResult {
Ok(())
}
}
pub struct FeatureState(Mutex<Vec<Box<dyn Feature>>>);
impl FeatureState {
pub fn new() -> Self {
Self(Mutex::new(vec![Box::new(InstanceSync::default())]))
}
}
impl FeatureState {
pub async fn launch(&self, version: &GameVersion, account: &MinecraftAccount) -> FeatureResult {
for feature in self.0.lock().await.iter_mut() {
feature.launch(version, account)?;
}
Ok(())
}
pub async fn after_launch(
&self,
version: &GameVersion,
account: &MinecraftAccount,
) -> FeatureResult {
for feature in self.0.lock().await.iter_mut() {
feature.after_launch(version, account)?;
}
Ok(())
}
}
+15 -7
View File
@@ -16,7 +16,7 @@ use lyceris::{
use tauri::{Emitter as _, State}; use tauri::{Emitter as _, State};
use crate::{GameVersion, SharedState}; use crate::{features::FeatureState, GameVersion, SharedState};
pub fn launcher_dir() -> PathBuf { pub fn launcher_dir() -> PathBuf {
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
@@ -47,6 +47,7 @@ pub fn launcher_dir() -> PathBuf {
pub async fn launch_game( pub async fn launch_game(
app: tauri::AppHandle, app: tauri::AppHandle,
state: State<'_, SharedState>, state: State<'_, SharedState>,
feature_state: State<'_, FeatureState>,
version: GameVersion, version: GameVersion,
account: MinecraftAccount, account: MinecraftAccount,
) -> Result<(), String> { ) -> Result<(), String> {
@@ -95,14 +96,14 @@ pub async fn launch_game(
launcher_dir().join(&version.id), launcher_dir().join(&version.id),
version.id.clone(), version.id.clone(),
lyceris::auth::AuthMethod::Microsoft { lyceris::auth::AuthMethod::Microsoft {
username: account.username, username: account.username.clone(),
xuid: account.xuid, xuid: account.xuid.clone(),
uuid: account.uuid, uuid: account.uuid.clone(),
access_token: account.access_token, access_token: account.access_token.clone(),
refresh_token: account.refresh_token, refresh_token: account.refresh_token.clone(),
}, },
) )
.loader(Fabric(version.loader_version).into()) .loader(Fabric(version.loader_version.clone()).into())
.memory(lyceris::minecraft::config::Memory::Megabyte( .memory(lyceris::minecraft::config::Memory::Megabyte(
state.lock().unwrap().settings.max_memory as u64, state.lock().unwrap().settings.max_memory as u64,
)) ))
@@ -124,6 +125,8 @@ pub async fn launch_game(
app.emit("launch-status", "Launching").unwrap(); app.emit("launch-status", "Launching").unwrap();
feature_state.inner().launch(&version, &account).await?;
launch(&config, Some(&emitter)) launch(&config, Some(&emitter))
.await .await
.map_err(|e| e.to_string())? .map_err(|e| e.to_string())?
@@ -131,6 +134,11 @@ pub async fn launch_game(
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
feature_state
.inner()
.after_launch(&version, &account)
.await?;
app.emit("is-launching", "false").unwrap(); app.emit("is-launching", "false").unwrap();
app.emit("launch-status", "").unwrap(); app.emit("launch-status", "").unwrap();
emit_progress(&app, 0.0); emit_progress(&app, 0.0);
+1
View File
@@ -1,4 +1,5 @@
pub mod commands; pub mod commands;
pub mod features;
pub mod launcher; pub mod launcher;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
+2 -1
View File
@@ -1,7 +1,7 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!! // Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use saturn_launcher_lib::load_state; use saturn_launcher_lib::{features::FeatureState, load_state};
use tauri::{Emitter, Manager, WindowEvent}; use tauri::{Emitter, Manager, WindowEvent};
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
@@ -9,6 +9,7 @@ fn main() {
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
.manage(load_state()) .manage(load_state())
.manage(FeatureState::new())
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
// Saturn Launcher Commands // Saturn Launcher Commands
saturn_launcher_lib::commands::get_installed_mods, saturn_launcher_lib::commands::get_installed_mods,