mirror of
https://github.com/Novattz/creamlinux-installer.git
synced 2026-05-02 04:52:03 -04:00
conflict backend stuff #89
This commit is contained in:
@@ -10,6 +10,7 @@ mod searcher;
|
|||||||
mod unlockers;
|
mod unlockers;
|
||||||
mod smokeapi_config;
|
mod smokeapi_config;
|
||||||
|
|
||||||
|
use crate::unlockers::{CreamLinux, SmokeAPI, Unlocker};
|
||||||
use dlc_manager::DlcInfoWithState;
|
use dlc_manager::DlcInfoWithState;
|
||||||
use installer::{Game, InstallerAction, InstallerType};
|
use installer::{Game, InstallerAction, InstallerType};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
@@ -456,6 +457,146 @@ fn delete_smokeapi_config(game_path: String) -> Result<(), String> {
|
|||||||
smokeapi_config::delete_config(&game_path)
|
smokeapi_config::delete_config(&game_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn resolve_platform_conflict(
|
||||||
|
game_id: String,
|
||||||
|
conflict_type: String, // "cream-to-proton" or "smoke-to-native"
|
||||||
|
state: State<'_, AppState>,
|
||||||
|
app_handle: tauri::AppHandle,
|
||||||
|
) -> Result<Game, String> {
|
||||||
|
info!(
|
||||||
|
"Resolving platform conflict for game {}: {}",
|
||||||
|
game_id, conflict_type
|
||||||
|
);
|
||||||
|
|
||||||
|
let game = {
|
||||||
|
let games = state.games.lock();
|
||||||
|
games
|
||||||
|
.get(&game_id)
|
||||||
|
.cloned()
|
||||||
|
.ok_or_else(|| format!("Game with ID {} not found", game_id))?
|
||||||
|
};
|
||||||
|
|
||||||
|
let game_title = game.title.clone();
|
||||||
|
|
||||||
|
// Emit progress
|
||||||
|
installer::emit_progress(
|
||||||
|
&app_handle,
|
||||||
|
&format!("Resolving Conflict: {}", game_title),
|
||||||
|
"Removing conflicting files...",
|
||||||
|
50.0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Perform the appropriate removal based on conflict type
|
||||||
|
match conflict_type.as_str() {
|
||||||
|
"cream-to-proton" => {
|
||||||
|
// Remove CreamLinux files (bypassing native check)
|
||||||
|
info!("Removing CreamLinux files from Proton game: {}", game_title);
|
||||||
|
|
||||||
|
CreamLinux::uninstall_from_game(&game.path, &game.id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Failed to remove CreamLinux files: {}", e))?;
|
||||||
|
|
||||||
|
// Remove version from manifest
|
||||||
|
crate::cache::remove_creamlinux_version(&game.path)?;
|
||||||
|
}
|
||||||
|
"smoke-to-native" => {
|
||||||
|
// Remove SmokeAPI files (bypassing proton check)
|
||||||
|
info!("Removing SmokeAPI files from native game: {}", game_title);
|
||||||
|
|
||||||
|
// For native games, we need to manually remove backup files since
|
||||||
|
// the main DLL might already be gone
|
||||||
|
// Look for and remove *_o.dll backup files
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
let mut removed_files = false;
|
||||||
|
|
||||||
|
for entry in WalkDir::new(&game.path)
|
||||||
|
.max_depth(5)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
{
|
||||||
|
let path = entry.path();
|
||||||
|
if !path.is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = path.file_name().unwrap_or_default().to_string_lossy();
|
||||||
|
|
||||||
|
// Remove steam_api*_o.dll backup files
|
||||||
|
if filename.starts_with("steam_api") && filename.ends_with("_o.dll") {
|
||||||
|
match std::fs::remove_file(path) {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("Removed SmokeAPI backup file: {}", path.display());
|
||||||
|
removed_files = true;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to remove backup file {}: {}", path.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also try the normal uninstall if api_files are present
|
||||||
|
if !game.api_files.is_empty() {
|
||||||
|
let api_files_str = game.api_files.join(",");
|
||||||
|
if let Err(e) = SmokeAPI::uninstall_from_game(&game.path, &api_files_str).await {
|
||||||
|
// Don't fail if this errors - we might have already cleaned up manually above
|
||||||
|
warn!("SmokeAPI uninstall warning: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !removed_files {
|
||||||
|
warn!("No SmokeAPI files found to remove for: {}", game_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove version from manifest
|
||||||
|
crate::cache::remove_smokeapi_version(&game.path)?;
|
||||||
|
}
|
||||||
|
_ => return Err(format!("Invalid conflict type: {}", conflict_type)),
|
||||||
|
}
|
||||||
|
|
||||||
|
installer::emit_progress(
|
||||||
|
&app_handle,
|
||||||
|
&format!("Conflict Resolved: {}", game_title),
|
||||||
|
"Conflicting files have been removed successfully!",
|
||||||
|
100.0,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update game state
|
||||||
|
let updated_game = {
|
||||||
|
let mut games_map = state.games.lock();
|
||||||
|
let game = games_map
|
||||||
|
.get_mut(&game_id)
|
||||||
|
.ok_or_else(|| format!("Game with ID {} not found after conflict resolution", game_id))?;
|
||||||
|
|
||||||
|
match conflict_type.as_str() {
|
||||||
|
"cream-to-proton" => {
|
||||||
|
game.cream_installed = false;
|
||||||
|
}
|
||||||
|
"smoke-to-native" => {
|
||||||
|
game.smoke_installed = false;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
game.installing = false;
|
||||||
|
game.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = app_handle.emit("game-updated", &updated_game) {
|
||||||
|
warn!("Failed to emit game-updated event: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Platform conflict resolved successfully for: {}", game_title);
|
||||||
|
Ok(updated_game)
|
||||||
|
}
|
||||||
|
|
||||||
fn setup_logging() -> Result<(), Box<dyn std::error::Error>> {
|
fn setup_logging() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use log4rs::append::file::FileAppender;
|
use log4rs::append::file::FileAppender;
|
||||||
@@ -516,6 +657,7 @@ fn main() {
|
|||||||
read_smokeapi_config,
|
read_smokeapi_config,
|
||||||
write_smokeapi_config,
|
write_smokeapi_config,
|
||||||
delete_smokeapi_config,
|
delete_smokeapi_config,
|
||||||
|
resolve_platform_conflict,
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
info!("Tauri application setup");
|
info!("Tauri application setup");
|
||||||
|
|||||||
@@ -256,11 +256,7 @@ fn check_creamlinux_installed(game_path: &Path) -> bool {
|
|||||||
|
|
||||||
// Check if a game has SmokeAPI installed
|
// Check if a game has SmokeAPI installed
|
||||||
fn check_smokeapi_installed(game_path: &Path, api_files: &[String]) -> bool {
|
fn check_smokeapi_installed(game_path: &Path, api_files: &[String]) -> bool {
|
||||||
if api_files.is_empty() {
|
// First check the provided api_files for backup files
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SmokeAPI creates backups with _o.dll suffix
|
|
||||||
for api_file in api_files {
|
for api_file in api_files {
|
||||||
let api_path = game_path.join(api_file);
|
let api_path = game_path.join(api_file);
|
||||||
let api_dir = api_path.parent().unwrap_or(game_path);
|
let api_dir = api_path.parent().unwrap_or(game_path);
|
||||||
@@ -275,6 +271,28 @@ fn check_smokeapi_installed(game_path: &Path, api_files: &[String]) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also scan for orphaned backup files (in case the main DLL was removed)
|
||||||
|
// This handles the Proton->Native switch case where steam_api*.dll is gone
|
||||||
|
// but steam_api*_o.dll backup remains
|
||||||
|
for entry in WalkDir::new(game_path)
|
||||||
|
.max_depth(5)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
{
|
||||||
|
let path = entry.path();
|
||||||
|
if !path.is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = path.file_name().unwrap_or_default().to_string_lossy();
|
||||||
|
|
||||||
|
// Look for steam_api*_o.dll backup files (SmokeAPI pattern)
|
||||||
|
if filename.starts_with("steam_api") && filename.ends_with("_o.dll") {
|
||||||
|
debug!("Found orphaned SmokeAPI backup file: {}", path.display());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -631,12 +649,10 @@ pub async fn find_installed_games(steamapps_paths: &[PathBuf]) -> Vec<GameInfo>
|
|||||||
// Check for CreamLinux installation
|
// Check for CreamLinux installation
|
||||||
let cream_installed = check_creamlinux_installed(&game_path);
|
let cream_installed = check_creamlinux_installed(&game_path);
|
||||||
|
|
||||||
// Check for SmokeAPI installation (only for non-native games with Steam API DLLs)
|
// Check for SmokeAPI installation
|
||||||
let smoke_installed = if !is_native && !api_files.is_empty() {
|
// For Proton games: check if api_files exist
|
||||||
check_smokeapi_installed(&game_path, &api_files)
|
// For Native games: ALSO check for orphaned backup files (proton->native switch)
|
||||||
} else {
|
let smoke_installed = check_smokeapi_installed(&game_path, &api_files);
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the game info
|
// Create the game info
|
||||||
let game_info = GameInfo {
|
let game_info = GameInfo {
|
||||||
|
|||||||
Reference in New Issue
Block a user