diff --git a/src-tauri/src/file_helpers.rs b/src-tauri/src/file_helpers.rs index b0d7987..3ec0c43 100644 --- a/src-tauri/src/file_helpers.rs +++ b/src-tauri/src/file_helpers.rs @@ -63,7 +63,7 @@ pub fn copy_file(path: String, new_path: String) -> bool { let path_buf = std::path::PathBuf::from(&path); // If the new path doesn't exist, create it. - if !dir_exists(new_path_buf.pop().to_string().as_str()) { + if !dir_exists(std::path::PathBuf::from(&new_path).pop().to_string().as_str()) { std::fs::create_dir_all(&new_path).unwrap(); } @@ -85,7 +85,7 @@ pub fn copy_file_with_new_name(path: String, new_path: String, new_name: String) let path_buf = std::path::PathBuf::from(&path); // If the new path doesn't exist, create it. - if !dir_exists(new_path_buf.pop().to_string().as_str()) { + if !dir_exists(std::path::PathBuf::from(&new_path).pop().to_string().as_str()) { match std::fs::create_dir_all(&new_path) { Ok(_) => {} Err(e) => { @@ -95,8 +95,10 @@ pub fn copy_file_with_new_name(path: String, new_path: String, new_name: String) }; } + new_path_buf.push(new_name); + // Copy old to new - match std::fs::copy(&path_buf, format!("{}/{}", new_path, new_name)) { + match std::fs::copy(&path_buf, &new_path_buf) { Ok(_) => true, Err(e) => { println!("Failed to copy file: {}", e); diff --git a/src-tauri/src/metadata_patcher.rs b/src-tauri/src/metadata_patcher.rs index 0403454..7669c3e 100644 --- a/src-tauri/src/metadata_patcher.rs +++ b/src-tauri/src/metadata_patcher.rs @@ -1,8 +1,5 @@ use regex::Regex; -use std::fs::File; -use std::fs::OpenOptions; -use std::io::Read; -use std::io::Write; +use std::{fs, path::Path, fs::File, fs::OpenOptions, io::Read, io::Write}; // For these two functions, a non-zero return value indicates failure. extern "C" { @@ -13,6 +10,12 @@ extern "C" { #[tauri::command] pub fn patch_metadata(metadata_folder: &str) -> bool { let metadata_file = &(metadata_folder.to_owned() + "\\global-metadata-unpatched.dat"); + // check if metadata_file exists + if !Path::new(metadata_file).exists() { + println!("Metadata file not found"); + return false; + } + println!("Patching metadata file: {}", metadata_file); let decrypted = decrypt_metadata(metadata_file); if do_vecs_match(&decrypted, &Vec::new()) { @@ -111,20 +114,17 @@ fn replace_keys(data: &[u8]) -> Vec { fn replace_rsa_key(old_data: &str, to_replace: &str, file_name: &str) -> String { // Read dispatch key file unsafe { - // Get key folder from exe path - let mut exe_path = std::env::current_exe().unwrap(); - exe_path.pop(); + // Get key path from current directory + let key_file_path = std::env::current_dir().unwrap().join("keys").join(file_name); - let key_folder = exe_path.to_str().unwrap().to_string(); - let mut new_key_file = match File::open(format!("{}/keys/{}", key_folder, file_name)) { + let key_data = match fs::read(&key_file_path) { Ok(file) => file, Err(e) => { - println!("Failed to open keys/{}: {}", file_name, e); + println!("Failed to open {}: {}", key_file_path.to_str().unwrap(), e); return String::new(); } }; - let mut key_data = Vec::new(); - new_key_file.read_to_end(&mut key_data).unwrap(); + let new_key = String::from_utf8_unchecked(key_data.to_vec()); // Replace old key with new key @@ -134,6 +134,7 @@ fn replace_rsa_key(old_data: &str, to_replace: &str, file_name: &str) -> String fn encrypt_metadata(old_data: &[u8]) -> Vec { let mut data = old_data.to_vec(); + let success = unsafe { encrypt_global_metadata(data.as_mut_ptr(), data.len()) } == 0; if success { println!("Successfully encrypted global-metadata"); diff --git a/src/ui/components/ServerLaunchSection.tsx b/src/ui/components/ServerLaunchSection.tsx index 0f8a186..b05d422 100644 --- a/src/ui/components/ServerLaunchSection.tsx +++ b/src/ui/components/ServerLaunchSection.tsx @@ -12,7 +12,7 @@ import Plus from '../../resources/icons/plus.svg' import './ServerLaunchSection.css' import { dataDir } from '@tauri-apps/api/path' -import { getGameExecutable } from '../../utils/game' +import { getGameExecutable, getGameVersion } from '../../utils/game' import { patchGame, unpatchGame } from '../../utils/metadata' interface IProps { @@ -110,6 +110,24 @@ export default class ServerLaunchSection extends React.Component // Connect to proxy if (config.toggle_grasscutter) { if (config.patch_metadata) { + const gameVersion = await getGameVersion() + console.log(gameVersion) + + if(gameVersion == null) { + alert('Game version could not be determined. Please make sure you have the game correctly selected and try again.') + return + } + + if(gameVersion?.major == 2 && gameVersion?.minor < 8) { + alert('Game version is too old for metadata patching. Please disable metadata patching in the settings and try again.') + return + } + + if(gameVersion?.major == 3 && gameVersion?.minor >= 1) { + alert('Game version is too new for metadata patching. Please disable metadata patching in the settings to launch the game.\nNOTE: You will require a UA patch to play the game.') + return + } + const patched = await patchGame() if (!patched) { diff --git a/src/utils/game.ts b/src/utils/game.ts index 2505a5e..27baadc 100644 --- a/src/utils/game.ts +++ b/src/utils/game.ts @@ -1,3 +1,4 @@ +import { invoke } from '@tauri-apps/api' import { getConfig } from './configuration' export async function getGameExecutable() { @@ -25,3 +26,34 @@ export async function getGameFolder() { return path } + +export async function getGameDataFolder() { + const gameExec = await getGameExecutable() + + if (!gameExec) { + return null + } + + return (await getGameFolder()) + '\\' + gameExec.replace('.exe', '_Data') +} + +export async function getGameVersion() { + const GameData = await getGameDataFolder(); + + if (!GameData) { + return null + } + + const settings = JSON.parse(await invoke('read_file', { + path: GameData + '\\StreamingAssets\\asb_settings.json', + })) + + const versionRaw = settings.variance.split('.'); + const version = { + major: parseInt(versionRaw[0]), + minor: parseInt(versionRaw[1].split('_')[0]), + release: parseInt(versionRaw[1].split('_')[1]), + } + + return version; +} diff --git a/src/utils/metadata.ts b/src/utils/metadata.ts index 19e87f1..8daf49b 100644 --- a/src/utils/metadata.ts +++ b/src/utils/metadata.ts @@ -1,7 +1,7 @@ import { invoke } from '@tauri-apps/api' import { dataDir } from '@tauri-apps/api/path' import DownloadHandler from './download' -import { getGameExecutable, getGameFolder } from './game' +import { getGameDataFolder, getGameExecutable, getGameFolder, getGameVersion } from './game' export async function patchMetadata() { const metadataExists = await invoke('dir_exists', { @@ -171,13 +171,13 @@ export async function unpatchGame() { } export async function getGameMetadataPath() { - const gameExec = await getGameExecutable() + const gameData = await getGameDataFolder() - if (!gameExec) { + if (!gameData) { return null } - return ((await getGameFolder()) + '\\' + gameExec.replace('.exe', '_Data') + '\\Managed\\Metadata').replace( + return (gameData + '\\Managed\\Metadata').replace( /\\/g, '/' ) @@ -188,6 +188,7 @@ export async function getBackupMetadataPath() { } export async function globalMetadataLink() { + // TODO: Get metadata based on current game version. const versionAPIUrl = 'https://sdk-os-static.mihoyo.com/hk4e_global/mdk/launcher/api/resource?channel_id=1&key=gcStgarh&launcher_id=10&sub_channel_id=0'