feat: implement osu! installation validation
This commit is contained in:
1
src-tauri/Cargo.lock
generated
1
src-tauri/Cargo.lock
generated
@@ -1084,6 +1084,7 @@ dependencies = [
|
||||
"tauri-plugin-shell",
|
||||
"tauri-plugin-single-instance",
|
||||
"tauri-plugin-sql",
|
||||
"winreg 0.55.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@@ -27,6 +27,7 @@ tauri-plugin-sql = "2.3.0"
|
||||
tauri-plugin-dialog = "2.3.0"
|
||||
tauri-plugin-fs = "2.4.0"
|
||||
hardware-id = "0.3.0"
|
||||
winreg = "0.55.0"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-single-instance = "2.3.0"
|
||||
|
@@ -1,6 +1,12 @@
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
use hardware_id::get_id;
|
||||
use std::path::PathBuf;
|
||||
use tauri::Manager;
|
||||
use winreg::enums::*;
|
||||
use winreg::RegKey;
|
||||
|
||||
use crate::utils::check_folder_completeness;
|
||||
mod utils;
|
||||
|
||||
#[tauri::command]
|
||||
fn get_hwid() -> String {
|
||||
@@ -8,6 +14,122 @@ fn get_hwid() -> String {
|
||||
hwid.into()
|
||||
}
|
||||
|
||||
#[tauri::command(rename_all = "snake_case")]
|
||||
fn valid_osu_folder(folder: String) -> bool {
|
||||
// List of files that should be present in the osu! installation folder
|
||||
let osu_folder_files = [
|
||||
"avcodec-51.dll",
|
||||
"avformat-52.dll",
|
||||
"avutil-49.dll",
|
||||
"bass.dll",
|
||||
"bass_fx.dll",
|
||||
"collection.db",
|
||||
"d3dcompiler_47.dll",
|
||||
"libEGL.dll",
|
||||
"libGLESv2.dll",
|
||||
"Microsoft.Ink.dll",
|
||||
"OpenTK.dll",
|
||||
"osu!.cfg",
|
||||
"osu!.db",
|
||||
"osu!.exe",
|
||||
"osu!auth.dll",
|
||||
"osu!gameplay.dll",
|
||||
"osu!seasonal.dll",
|
||||
"osu!ui.dll",
|
||||
"presence.db",
|
||||
"pthreadGC2.dll",
|
||||
"scores.db",
|
||||
];
|
||||
|
||||
let path = PathBuf::from(folder);
|
||||
let match_percentage = check_folder_completeness(path, &osu_folder_files) >= 70.0;
|
||||
if match_percentage {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn find_osu_installation() -> Option<String> {
|
||||
// List of possible registry paths to check for osu! installation
|
||||
let hklm_registry_paths = ["SOFTWARE\\Classes\\osu\\DefaultIcon"];
|
||||
|
||||
let hkcr_registry_paths = [
|
||||
"osustable.File.osk\\DefaultIcon",
|
||||
"osustable.File.osr\\DefaultIcon",
|
||||
"osustable.File.osz\\DefaultIcon",
|
||||
];
|
||||
|
||||
let osu_folder_files = [
|
||||
"avcodec-51.dll",
|
||||
"avformat-52.dll",
|
||||
"avutil-49.dll",
|
||||
"bass.dll",
|
||||
"bass_fx.dll",
|
||||
"collection.db",
|
||||
"d3dcompiler_47.dll",
|
||||
"libEGL.dll",
|
||||
"libGLESv2.dll",
|
||||
"Microsoft.Ink.dll",
|
||||
"OpenTK.dll",
|
||||
"osu!.cfg",
|
||||
"osu!.db",
|
||||
"osu!.exe",
|
||||
"osu!auth.dll",
|
||||
"osu!gameplay.dll",
|
||||
"osu!seasonal.dll",
|
||||
"osu!ui.dll",
|
||||
"presence.db",
|
||||
"pthreadGC2.dll",
|
||||
"scores.db",
|
||||
];
|
||||
|
||||
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
|
||||
|
||||
for reg_path in &hklm_registry_paths {
|
||||
if let Ok(subkey) = hklm.open_subkey_with_flags(reg_path, KEY_READ | KEY_WOW64_32KEY) {
|
||||
let value_names = [""];
|
||||
for value_name in &value_names {
|
||||
if let Ok(value) = subkey.get_value::<String, _>(value_name) {
|
||||
let trimmed = value.trim_matches('"');
|
||||
let stripped = trimmed.strip_suffix(",0").unwrap_or(trimmed);
|
||||
let path = PathBuf::from(stripped.trim());
|
||||
if let Some(parent) = path.parent() {
|
||||
let match_percentage = check_folder_completeness(parent, &osu_folder_files);
|
||||
|
||||
if match_percentage >= 70.0 {
|
||||
return Some(parent.to_string_lossy().into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let hkcr = RegKey::predef(HKEY_CLASSES_ROOT);
|
||||
|
||||
for reg_path in &hkcr_registry_paths {
|
||||
if let Ok(subkey) = hkcr.open_subkey_with_flags(reg_path, KEY_READ | KEY_WOW64_32KEY) {
|
||||
let value_names = [""];
|
||||
for value_name in &value_names {
|
||||
if let Ok(value) = subkey.get_value::<String, _>(value_name) {
|
||||
let trimmed = value.trim_matches('"');
|
||||
let stripped = trimmed.strip_suffix(",1").unwrap_or(trimmed);
|
||||
let path = PathBuf::from(stripped.trim());
|
||||
if let Some(parent) = path.parent() {
|
||||
let match_percentage = check_folder_completeness(parent, &osu_folder_files);
|
||||
|
||||
if match_percentage >= 70.0 {
|
||||
return Some(parent.to_string_lossy().into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
let mut builder = tauri::Builder::default().plugin(tauri_plugin_fs::init());
|
||||
@@ -23,7 +145,7 @@ pub fn run() {
|
||||
}
|
||||
|
||||
builder
|
||||
.invoke_handler(tauri::generate_handler![get_hwid])
|
||||
.invoke_handler(tauri::generate_handler![get_hwid, find_osu_installation, valid_osu_folder])
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_sql::Builder::default().build())
|
||||
|
24
src-tauri/src/utils.rs
Normal file
24
src-tauri/src/utils.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use std::path::Path;
|
||||
|
||||
/// Checks the presence of required files in a folder and returns the percentage found.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `folder_path` - The path to the folder to check.
|
||||
/// * `required_files` - A slice of file names that should be present in the folder.
|
||||
///
|
||||
/// # Returns
|
||||
/// * `f32` - The percentage (0.0 to 100.0) of required files found in the folder.
|
||||
pub fn check_folder_completeness<P: AsRef<Path>>(folder_path: P, required_files: &[&str]) -> f32 {
|
||||
let mut found = 0;
|
||||
for file in required_files {
|
||||
let file_path = folder_path.as_ref().join(file);
|
||||
if file_path.exists() {
|
||||
found += 1;
|
||||
}
|
||||
}
|
||||
if required_files.is_empty() {
|
||||
100.0
|
||||
} else {
|
||||
(found as f32 / required_files.len() as f32) * 100.0
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user