From 5e340df9d83a4f92de3678bd89b8919dbba52808 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Wed, 12 Nov 2025 23:19:23 +0100 Subject: [PATCH] wip --- crates/lanspread-peer/src/lib.rs | 98 +++++-------------- .../src-tauri/src/lib.rs | 52 +++++----- 2 files changed, 52 insertions(+), 98 deletions(-) diff --git a/crates/lanspread-peer/src/lib.rs b/crates/lanspread-peer/src/lib.rs index dc50731..8402df7 100644 --- a/crates/lanspread-peer/src/lib.rs +++ b/crates/lanspread-peer/src/lib.rs @@ -12,7 +12,6 @@ use std::{ }; use bytes::BytesMut; -use lanspread_compat::eti::EtiGame; use lanspread_db::db::{Game, GameDB, GameFileDescription}; use lanspread_mdns::{LANSPREAD_SERVICE_TYPE, MdnsAdvertiser, discover_service}; use lanspread_proto::{Message, Request, Response}; @@ -24,9 +23,6 @@ use s2n_quic::{ provider::limits::Limits, stream::BidirectionalStream, }; - -/// Handle for loading ETI games from Tauri resources -pub type EtiGamesLoader = Arc eyre::Result> + Send + Sync>; use tokio::{ fs::OpenOptions, io::{AsyncSeekExt, AsyncWriteExt}, @@ -86,15 +82,6 @@ impl From for PeerError { pub fn start_peer( game_dir: String, tx_notify_ui: UnboundedSender, -) -> eyre::Result> { - start_peer_with_eti_loader(game_dir, tx_notify_ui, None) -} - -/// Initialize and start the peer system with ETI games loader -pub fn start_peer_with_eti_loader( - game_dir: String, - tx_notify_ui: UnboundedSender, - eti_games_loader: Option, ) -> eyre::Result> { log::info!("Starting peer system with game directory: {game_dir}"); @@ -103,7 +90,7 @@ pub fn start_peer_with_eti_loader( // Start the peer in a background task let tx_control_clone = tx_control.clone(); tokio::spawn(async move { - if let Err(e) = run_peer_with_eti_loader(rx_control, tx_notify_ui, eti_games_loader).await { + if let Err(e) = run_peer(rx_control, tx_notify_ui).await { log::error!("Peer system failed: {e}"); } }); @@ -1090,28 +1077,12 @@ async fn retry_failed_chunks( exhausted } -/// Load games from the ETI game.db resource file -fn load_eti_games(eti_games_loader: Option) -> eyre::Result> { - if let Some(loader) = eti_games_loader { - loader() - } else { - log::warn!("ETI games loader not provided - returning empty games list"); - Ok(Vec::new()) - } -} - -/// Load local game database combining ETI games and locally installed games -async fn load_local_game_db_with_eti( - game_dir: &str, - eti_games_loader: Option, -) -> eyre::Result { +/// Load local game database combining locally installed games +async fn load_local_game_db(game_dir: &str) -> eyre::Result { let game_path = PathBuf::from(game_dir); + let mut games = Vec::new(); - // Load games from ETI database using the loader (from() sets installed=false, local_version=None) - let eti_games = load_eti_games(eti_games_loader)?; - let mut games: Vec = eti_games.into_iter().map(Into::into).collect(); - - // Scan game directory and mark found games as installed + // Scan game directory and create entries for installed games let mut entries = tokio::fs::read_dir(&game_path).await?; while let Some(entry) = entries.next_entry().await? { let path = entry.path(); @@ -1120,31 +1091,23 @@ async fn load_local_game_db_with_eti( { // Check if this game has a version.ini file if let Ok(version) = lanspread_db::db::read_version_from_ini(&path) { - // Update existing game or create new one if not found in ETI DB - if let Some(game) = games.iter_mut().find(|g| g.id == game_id) { - game.installed = true; - game.local_version.clone_from(&version); - // Keep the ETI size for informational purposes - } else { - // Game not found in ETI DB, create basic entry - let size = calculate_directory_size(&path).await?; - let game = Game { - id: game_id.to_string(), - name: game_id.to_string(), - description: String::new(), - release_year: String::new(), - publisher: String::new(), - max_players: 1, - version: "1.0".to_string(), - genre: String::new(), - size, - thumbnail: None, - installed: true, - eti_game_version: version.clone(), - local_version: version, - }; - games.push(game); - } + let size = calculate_directory_size(&path).await?; + let game = Game { + id: game_id.to_string(), + name: game_id.to_string(), + description: String::new(), + release_year: String::new(), + publisher: String::new(), + max_players: 1, + version: "1.0".to_string(), + genre: String::new(), + size, + thumbnail: None, + installed: true, + eti_game_version: version.clone(), + local_version: version, + }; + games.push(game); } } } @@ -1174,14 +1137,12 @@ struct Ctx { game_dir: Arc>>, local_game_db: Arc>>, peer_game_db: Arc>, - eti_games_loader: Option, } #[derive(Clone)] struct PeerCtx { game_dir: Arc>>, local_game_db: Arc>>, - eti_games_loader: Option, } impl std::fmt::Debug for PeerCtx { @@ -1189,7 +1150,6 @@ impl std::fmt::Debug for PeerCtx { f.debug_struct("PeerCtx") .field("game_dir", &"...") .field("local_game_db", &"...") - .field("eti_games_loader", &self.eti_games_loader.is_some()) .finish() } } @@ -1201,30 +1161,19 @@ impl std::fmt::Debug for PeerCtx { /// This function will panic if the games folder is None after being checked for None. /// The panic occurs at line 908 where `games_folder.expect("checked above")` is called. pub async fn run_peer( - rx_control: UnboundedReceiver, - tx_notify_ui: UnboundedSender, -) -> eyre::Result<()> { - run_peer_with_eti_loader(rx_control, tx_notify_ui, None).await -} - -/// Main peer execution loop that handles peer commands and manages the peer system with ETI games loader. -pub async fn run_peer_with_eti_loader( mut rx_control: UnboundedReceiver, tx_notify_ui: UnboundedSender, - eti_games_loader: Option, ) -> eyre::Result<()> { // peer context let ctx = Ctx { game_dir: Arc::new(RwLock::new(None)), local_game_db: Arc::new(RwLock::new(None)), peer_game_db: Arc::new(RwLock::new(PeerGameDB::new())), - eti_games_loader, }; let peer_ctx = PeerCtx { game_dir: ctx.game_dir.clone(), local_game_db: ctx.local_game_db.clone(), - eti_games_loader: ctx.eti_games_loader.clone(), }; // Start server component @@ -1491,9 +1440,8 @@ async fn handle_set_game_dir_command(ctx: &Ctx, game_dir: String) { // Load local game database when game directory is set let game_dir = game_dir.clone(); let local_game_db = ctx.local_game_db.clone(); - let eti_games_loader = ctx.eti_games_loader.clone(); tokio::spawn(async move { - match load_local_game_db_with_eti(&game_dir, eti_games_loader).await { + match load_local_game_db(&game_dir).await { Ok(db) => { *local_game_db.write().await = Some(db); log::info!("Local game database loaded successfully"); diff --git a/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs b/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs index d375c59..fe3080b 100644 --- a/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs +++ b/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs @@ -7,7 +7,7 @@ use std::{ use eyre::bail; use lanspread_compat::eti::get_games; use lanspread_db::db::{Game, GameDB}; -use lanspread_peer::{EtiGamesLoader, PeerCommand, PeerEvent, start_peer_with_eti_loader}; +use lanspread_peer::{PeerCommand, PeerEvent, start_peer}; use tauri::{AppHandle, Emitter as _, Manager}; use tauri_plugin_shell::{ShellExt, process::Command}; use tokio::sync::{RwLock, mpsc::UnboundedSender}; @@ -521,33 +521,39 @@ pub fn run() { }; if !games_folder.is_empty() { - // Create ETI games loader that can access the Tauri resource - let app_handle_for_loader = app_handle_clone.clone(); - let eti_games_loader: EtiGamesLoader = Arc::new(move || { - let app_handle = app_handle_for_loader.clone(); - // Use tokio's block_in_place to call async function from sync context - tokio::task::block_in_place(move || { - tokio::runtime::Handle::current().block_on(async move { - // Resolve the game.db resource path - match app_handle.path().resolve("game.db", tauri::path::BaseDirectory::Resource) { - Ok(game_db_path) => { - get_games(&game_db_path).await - } - Err(e) => { - log::error!("Failed to resolve game.db resource: {e}"); - Err(eyre::eyre!("Failed to resolve game.db resource: {e}")) - } - } - }) - }) - }); + // Load ETI games from the game.db resource - this MUST succeed + let game_db_path = match app_handle_clone.path().resolve("game.db", tauri::path::BaseDirectory::Resource) { + Ok(path) => path, + Err(e) => { + log::error!("Failed to resolve game.db resource: {e}"); + panic!("game.db resource is mandatory - cannot continue"); + } + }; + + let eti_games = match get_games(&game_db_path).await { + Ok(games) => { + log::info!("Loaded {} ETI games from game.db", games.len()); + games + } + Err(e) => { + log::error!("Failed to load ETI games: {e}"); + panic!("game.db resource is mandatory - cannot continue"); + } + }; + + // Convert ETI games to GameDB and store in state + let games: Vec = eti_games.into_iter().map(Into::into).collect(); + { + let state = app_handle_clone.state::(); + *state.games.write().await = GameDB::from(games); + } // Only start peer system when we have a valid games directory - match start_peer_with_eti_loader(games_folder, tx_peer_event_clone, Some(eti_games_loader)) { + match start_peer(games_folder, tx_peer_event_clone) { Ok(peer_ctrl) => { let state = app_handle_clone.state::(); *state.peer_ctrl.write().await = Some(peer_ctrl); - log::info!("Peer system initialized successfully with games directory and ETI loader"); + log::info!("Peer system initialized successfully with games directory"); // Start peer discovery and request games from other peers request_games(state);