Changes from 1.2.1 - 1.5.1

Contains slightly modified commits from between 1.2.1 and 1.5.1.
This commit is contained in:
Thoronium
2024-10-30 13:18:07 -06:00
parent 31c60755af
commit f6f5eae31c
46 changed files with 2619 additions and 1669 deletions

View File

@@ -1,6 +1,6 @@
use file_diff::diff;
use std::fs;
use std::io::{Read, Write};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
#[tauri::command]
@@ -57,6 +57,11 @@ pub fn are_files_identical(path1: &str, path2: &str) -> bool {
diff(path1, path2)
}
#[tauri::command]
pub fn does_file_exist(path1: &str) -> bool {
fs::metadata(path1).is_ok()
}
#[tauri::command]
pub fn copy_file(path: String, new_path: String) -> bool {
let filename = &path.split('/').last().unwrap();
@@ -127,21 +132,46 @@ pub fn delete_file(path: String) -> bool {
#[tauri::command]
pub fn read_file(path: String) -> String {
let path_buf = PathBuf::from(&path);
let mut file = match fs::File::open(path_buf) {
Ok(file) => file,
Err(e) => {
println!("Failed to open file {}: {}", &path, e);
if path.contains("config") {
// Server.ts won't print the error so handle the message here for the user
println!("Server config not found or invalid. Be sure to run the server at least once to generate it before making edits.");
}
return String::new(); // Send back error for handling by the caller
}
};
println!("Debug: Reading file of path {}", path.clone(),);
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
// Version data is 3 bytes long, 3 bytes in
let ext = path_buf.extension().unwrap();
if ext.eq("bytes") {
let offset_bytes = 3;
let num_bytes = 3;
let mut byte_file = match std::fs::File::open(path_buf) {
Ok(byte_file) => byte_file,
Err(e) => {
println!("{}", e);
return String::new();
}
};
byte_file
.seek(SeekFrom::Start(offset_bytes))
.unwrap_or_default();
let mut buf = vec![0; num_bytes];
byte_file.read_exact(&mut buf).unwrap_or_default();
contents = String::from_utf8_lossy(&buf).to_string();
} else {
let mut file = match fs::File::open(path_buf) {
Ok(file) => file,
Err(e) => {
if path.contains("config") {
// Server.ts won't print the error so handle the message here for the user
println!("Server config not found or invalid. Be sure to run the server at least once to generate it before making edits.");
} else {
println!("Failed to open file: {}", e);
}
return String::new(); // Send back error for handling by the caller
}
};
file.read_to_string(&mut contents).unwrap();
}
contents
}

View File

@@ -28,12 +28,7 @@ pub async fn get_languages() -> std::collections::HashMap<String, String> {
for entry in lang_files {
let entry = entry.unwrap();
let path = entry.path();
let filename = path
.file_name()
.unwrap_or_else(|| panic!("Failed to get filename from path: {:?}", path))
.to_str()
.unwrap_or_else(|| panic!("Failed to convert filename to string: {:?}", path))
.to_string();
let filename = path.file_name().unwrap().to_str().unwrap();
let content = match std::fs::read_to_string(&path) {
Ok(x) => x,

View File

@@ -108,14 +108,14 @@ async fn parse_args(inp: &Vec<String>) -> Result<Args, ArgsError> {
std::process::exit(0);
}
// Patch if needed
if args.value_of("patch")? {
patch::patch_game(false, 0.to_string()).await;
}
if args.value_of("launch-game")? {
let game_path = config.game_install_path;
let game_args: String = args.value_of("game-args").unwrap_or_default();
// Patch if needed
if args.value_of("patch")? {
patch::patch_game().await;
}
let game_args: String = args.value_of("game-args").unwrap_or(String::new());
if game_path.is_some() {
if args.value_of("non-elevated-game")? {
@@ -154,8 +154,8 @@ async fn parse_args(inp: &Vec<String>) -> Result<Args, ArgsError> {
pathbuf.push("cultivation");
pathbuf.push("ca");
if args.value_of("other_redirects")? {
proxy::set_redirect_more();
if args.value_of("other-redirects")? {
// proxy::set_redirect_more(); // Unused
}
connect(8035, pathbuf.to_str().unwrap().to_string()).await;
@@ -218,7 +218,6 @@ fn main() -> Result<(), ArgsError> {
system_helpers::open_in_browser,
system_helpers::install_location,
system_helpers::is_elevated,
system_helpers::set_migoto_target,
system_helpers::set_migoto_delay,
system_helpers::wipe_registry,
system_helpers::get_platform,
@@ -229,7 +228,6 @@ fn main() -> Result<(), ArgsError> {
patch::unpatch_game,
proxy::set_proxy_addr,
proxy::generate_ca_files,
proxy::set_redirect_more,
release::get_latest_release,
unzip::unzip,
file_helpers::rename,
@@ -243,6 +241,7 @@ fn main() -> Result<(), ArgsError> {
file_helpers::are_files_identical,
file_helpers::read_file,
file_helpers::write_file,
file_helpers::does_file_exist,
downloader::download_file,
downloader::stop_download,
lang::get_lang,
@@ -297,7 +296,7 @@ fn enable_process_watcher(window: tauri::Window, process: String) {
thread::spawn(move || {
// Initial sleep for 8 seconds, since running 20 different injectors or whatever can take a while
std::thread::sleep(std::time::Duration::from_secs(10));
std::thread::sleep(std::time::Duration::from_secs(60));
let mut system = System::new_all();
@@ -336,7 +335,7 @@ fn enable_process_watcher(window: tauri::Window, process: String) {
fn enable_process_watcher(window: tauri::Window, process: String) {
drop(process);
thread::spawn(move || {
let end_time = Instant::now() + Duration::from_secs(60);
let end_time = Instant::now() + Duration::from_secs(90);
let game_thread = loop {
let mut lock = AAGL_THREAD.lock().unwrap();
if lock.is_some() {

View File

@@ -50,8 +50,90 @@ struct WhatToUnpach {
#[cfg(windows)]
#[tauri::command]
pub async fn patch_game() -> bool {
let patch_path = PathBuf::from(system_helpers::install_location()).join("patch/version.dll");
pub async fn patch_game(newer_game: bool, version: String) -> bool {
let mut patch_path;
// Altpatch first - Now using as hoyonet switch
if newer_game {
let alt_patch_path = PathBuf::from(system_helpers::install_location()).join("altpatch");
// Should handle overwriting backup with new version backup later
let backup_path = PathBuf::from(system_helpers::install_location())
.join("altpatch/original-mihoyonet.dll")
.to_str()
.unwrap()
.to_string();
let backup_exists = file_helpers::does_file_exist(&backup_path);
if !backup_exists {
let backup = file_helpers::copy_file_with_new_name(
get_game_rsa_path().await.unwrap()
+ &String::from("/GenshinImpact_Data/Plugins/mihoyonet.dll"),
alt_patch_path.clone().to_str().unwrap().to_string(),
String::from("original-mihoyonet.dll"),
);
if !backup {
println!("Unable to backup file!");
}
}
patch_path = PathBuf::from(system_helpers::install_location()).join("altpatch/mihoyonet.dll");
// Copy the other part of patch to game files
let alt_replaced = file_helpers::copy_file_with_new_name(
patch_path.clone().to_str().unwrap().to_string(),
get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins"),
String::from("mihoyonet.dll"),
);
if !alt_replaced {
return false;
}
/*** For replacing old backup file with new one, for example when version changes
* Currently replaces when it shouldn't. Will figure it out when it matters
* ***/
// else {
// // Check if game file matches backup
// let matching_alt_backup = file_helpers::are_files_identical(
// &backup_path.clone(),
// PathBuf::from(get_game_rsa_path().await.unwrap())
// .join("/GenshinImpact_Data/Plugins/mihoyonet.dll")
// .to_str()
// .unwrap(),
// );
// let is_alt_patched = file_helpers::are_files_identical(
// PathBuf::from(system_helpers::install_location()).join("altpatch/mihoyonet.dll").to_str().unwrap(),
// PathBuf::from(get_game_rsa_path().await.unwrap())
// .join("/GenshinImpact_Data/Plugins/mihoyonet.dll")
// .to_str()
// .unwrap(),
// );
// // Check if already alt patched
// if !matching_alt_backup {
// // Copy new backup if it is not patched
// if !is_alt_patched {
// file_helpers::copy_file_with_new_name(
// get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins/mihoyonet.dll"),
// alt_patch_path.clone().to_str().unwrap().to_string(),
// String::from("original-mihoyonet.dll"),
// );
// }
// }
// }
}
// Standard patch
patch_path = PathBuf::from(system_helpers::install_location()).join("patch/version.dll");
let i_ver = version.parse::<i32>().unwrap();
// For newer than 4.0, use specific patch files
if i_ver > 40 {
let patch_version = format!("patch/{version}version.dll");
patch_path = PathBuf::from(system_helpers::install_location()).join(patch_version);
}
// Are we already patched with mhypbase? If so, that's fine, just continue as normal
let game_is_patched = file_helpers::are_files_identical(
@@ -70,6 +152,21 @@ pub async fn patch_game() -> bool {
return true;
}
// For 5.0 and up
if i_ver > 49 {
let replaced50 = file_helpers::copy_file_with_new_name(
patch_path.clone().to_str().unwrap().to_string(),
get_game_rsa_path().await.unwrap(),
String::from("Astrolabe.dll"),
);
if replaced50 {
return true;
} else {
return false;
}
}
// Copy the patch to game files
let replaced = file_helpers::copy_file_with_new_name(
patch_path.clone().to_str().unwrap().to_string(),
@@ -86,7 +183,7 @@ pub async fn patch_game() -> bool {
#[cfg(target_os = "linux")]
#[tauri::command]
pub async fn patch_game() -> bool {
pub async fn patch_game(_newer_game: bool, _version: String) -> bool {
let mut patch_state_mutex = PATCH_STATE.lock().await;
if patch_state_mutex.is_some() {
println!("Game already patched!");
@@ -170,6 +267,36 @@ pub async fn unpatch_game() -> bool {
.to_string(),
);
file_helpers::delete_file(
PathBuf::from(get_game_rsa_path().await.unwrap())
.join("Astrolabe.dll")
.to_str()
.unwrap()
.to_string(),
);
let core_patch_path = PathBuf::from(system_helpers::install_location());
let patch_path = core_patch_path.clone().join("altpatch/mihoyonet.dll");
let backup_path = core_patch_path
.clone()
.join("altpatch/original-mihoyonet.dll");
let is_alt_patched = file_helpers::are_files_identical(
patch_path.clone().to_str().unwrap(),
PathBuf::from(get_game_rsa_path().await.unwrap())
.join("GenshinImpact_Data/Plugins/mihoyonet.dll")
.to_str()
.unwrap(),
);
if is_alt_patched {
file_helpers::copy_file_with_new_name(
backup_path.clone().to_str().unwrap().to_string(),
get_game_rsa_path().await.unwrap() + &String::from("/GenshinImpact_Data/Plugins"),
String::from("mihoyonet.dll"),
);
}
deleted
}

View File

@@ -3,8 +3,6 @@
* https://github.com/omjadas/hudsucker/blob/main/examples/log.rs
*/
use crate::config::get_config;
use once_cell::sync::Lazy;
use std::{path::PathBuf, str::FromStr, sync::Mutex};
@@ -41,8 +39,6 @@ async fn shutdown_signal() {
// Global ver for getting server address.
static SERVER: Lazy<Mutex<String>> = Lazy::new(|| Mutex::new("http://localhost:443".to_string()));
static REDIRECT_MORE: Lazy<Mutex<bool>> = Lazy::new(|| Mutex::new(false));
#[derive(Clone)]
struct ProxyHandler;
@@ -58,11 +54,6 @@ pub fn set_proxy_addr(addr: String) {
println!("Set server to {}", SERVER.lock().unwrap());
}
#[tauri::command]
pub fn set_redirect_more() {
*REDIRECT_MORE.lock().unwrap() = true;
}
#[async_trait]
impl HttpHandler for ProxyHandler {
async fn handle_request(
@@ -72,93 +63,33 @@ impl HttpHandler for ProxyHandler {
) -> RequestOrResponse {
let uri = req.uri().to_string();
let mut more = get_config().redirect_more;
if uri.contains("hoyoverse.com")
|| uri.contains("mihoyo.com")
|| uri.contains("yuanshen.com")
|| uri.ends_with(".yuanshen.com:12401")
|| uri.contains("starrails.com")
|| uri.contains("bhsr.com")
|| uri.contains("bh3.com")
|| uri.contains("honkaiimpact3.com")
|| uri.contains("zenlesszonezero.com")
{
// Handle CONNECTs
if req.method().as_str() == "CONNECT" {
let builder = Response::builder()
.header("DecryptEndpoint", "Created")
.status(StatusCode::OK);
let res = builder.body(()).unwrap();
if *REDIRECT_MORE.lock().unwrap() {
more = Some(true);
}
match more {
Some(true) => {
if uri.contains("hoyoverse.com")
|| uri.contains("mihoyo.com")
|| uri.contains("yuanshen.com")
|| uri.contains("starrails.com")
|| uri.contains("bhsr.com")
|| uri.contains("bh3.com")
|| uri.contains("honkaiimpact3.com")
|| uri.contains("zenlesszonezero.com")
{
// Handle CONNECTs
if req.method().as_str() == "CONNECT" {
let builder = Response::builder()
.header("DecryptEndpoint", "Created")
.status(StatusCode::OK);
let res = builder.body(()).unwrap();
// Respond to CONNECT
*res.body()
} else {
let uri_path_and_query = req.uri().path_and_query().unwrap().as_str();
// Create new URI.
let new_uri =
Uri::from_str(format!("{}{}", SERVER.lock().unwrap(), uri_path_and_query).as_str())
.unwrap();
// Set request URI to the new one.
*req.uri_mut() = new_uri;
}
}
}
Some(false) => {
if uri.contains("hoyoverse.com")
|| uri.contains("mihoyo.com")
|| uri.contains("yuanshen.com")
{
// Handle CONNECTs
if req.method().as_str() == "CONNECT" {
let builder = Response::builder()
.header("DecryptEndpoint", "Created")
.status(StatusCode::OK);
let res = builder.body(()).unwrap();
// Respond to CONNECT
*res.body()
} else {
let uri_path_and_query = req.uri().path_and_query().unwrap().as_str();
// Create new URI.
let new_uri =
Uri::from_str(format!("{}{}", SERVER.lock().unwrap(), uri_path_and_query).as_str())
.unwrap();
// Set request URI to the new one.
*req.uri_mut() = new_uri;
}
}
}
// Use default as fallback
None => {
if uri.contains("hoyoverse.com")
|| uri.contains("mihoyo.com")
|| uri.contains("yuanshen.com")
{
// Handle CONNECTs
if req.method().as_str() == "CONNECT" {
let builder = Response::builder()
.header("DecryptEndpoint", "Created")
.status(StatusCode::OK);
let res = builder.body(()).unwrap();
// Respond to CONNECT
*res.body()
} else {
let uri_path_and_query = req.uri().path_and_query().unwrap().as_str();
// Create new URI.
let new_uri =
Uri::from_str(format!("{}{}", SERVER.lock().unwrap(), uri_path_and_query).as_str())
.unwrap();
// Set request URI to the new one.
*req.uri_mut() = new_uri;
}
}
// Respond to CONNECT
*res.body()
} else {
let uri_path_and_query = req.uri().path_and_query().unwrap().as_str();
// Create new URI.
let new_uri =
Uri::from_str(format!("{}{}", SERVER.lock().unwrap(), uri_path_and_query).as_str())
.unwrap();
// Set request URI to the new one.
*req.uri_mut() = new_uri;
}
}
@@ -176,26 +107,14 @@ impl HttpHandler for ProxyHandler {
async fn should_intercept(&mut self, _ctx: &HttpContext, _req: &Request<Body>) -> bool {
let uri = _req.uri().to_string();
let more = get_config().redirect_more;
match more {
Some(true) => {
uri.contains("hoyoverse.com")
|| uri.contains("mihoyo.com")
|| uri.contains("yuanshen.com")
|| uri.contains("starrails.com")
|| uri.contains("bhsr.com")
|| uri.contains("bh3.com")
|| uri.contains("honkaiimpact3.com")
|| uri.contains("zenlesszonezero.com")
}
Some(false) => {
uri.contains("hoyoverse.com") || uri.contains("mihoyo.com") || uri.contains("yuanshen.com")
}
None => {
uri.contains("hoyoverse.com") || uri.contains("mihoyo.com") || uri.contains("yuanshen.com")
}
}
uri.contains("hoyoverse.com")
|| uri.contains("mihoyo.com")
|| uri.contains("yuanshen.com")
|| uri.contains("starrails.com")
|| uri.contains("bhsr.com")
|| uri.contains("bh3.com")
|| uri.contains("honkaiimpact3.com")
|| uri.contains("zenlesszonezero.com")
}
}
@@ -307,7 +226,7 @@ pub fn connect_to_proxy(proxy_port: u16) {
Config::update(config);
}
#[cfg(target_od = "macos")]
#[cfg(target_os = "macos")]
pub fn connect_to_proxy(_proxy_port: u16) {
println!("No Mac support yet. Someone mail me a Macbook and I will do it B)")
}

View File

@@ -16,7 +16,6 @@ pub async fn get_latest_release() -> Release {
.unwrap();
let text = response.text().await.unwrap();
// This includes ip when github rate limits you, so avoid it for now to avoid leaks through screenshots
//println!("Response: {}", text);
// Parse "tag_name" from JSON

View File

@@ -390,44 +390,6 @@ pub fn install_location() -> String {
}
}
#[tauri::command]
pub fn set_migoto_target(window: tauri::Window, migoto_path: String) -> bool {
let mut migoto_pathbuf = PathBuf::from(migoto_path);
migoto_pathbuf.pop();
migoto_pathbuf.push("d3dx.ini");
let mut conf = match Ini::load_from_file(&migoto_pathbuf) {
Ok(c) => {
println!("Loaded migoto ini");
c
}
Err(e) => {
println!("Error loading migoto config: {}", e);
return false;
}
};
window.emit("migoto_set", &()).unwrap();
// Set options
conf
.with_section(Some("Loader"))
.set("target", "GenshinImpact.exe");
// Write file
match conf.write_to_file(&migoto_pathbuf) {
Ok(_) => {
println!("Wrote config!");
true
}
Err(e) => {
println!("Error writing config: {}", e);
false
}
}
}
#[tauri::command]
pub fn set_migoto_delay(migoto_path: String) -> bool {
let mut migoto_pathbuf = PathBuf::from(migoto_path);
@@ -448,9 +410,18 @@ pub fn set_migoto_delay(migoto_path: String) -> bool {
// Set options
conf.with_section(Some("Loader")).set("delay", "20");
conf
.with_section(Some("Include"))
.set("include", "ShaderFixes\\help.ini");
// Write file
match conf.write_to_file(&migoto_pathbuf) {
match conf.write_to_file_opt(
&migoto_pathbuf,
ini::WriteOption {
escape_policy: (ini::EscapePolicy::Nothing),
line_separator: (ini::LineSeparator::SystemDefault),
},
) {
Ok(_) => {
println!("Wrote delay!");
true
@@ -483,6 +454,31 @@ pub fn wipe_registry(exec_name: String) {
Ok(_) => (),
Err(e) => println!("Error wiping registry: {}", e),
}
match settings.set_value(
"MIHOYOSDK_ADL_PROD_CN_h3123967166",
&Data::String("".parse().unwrap()),
) {
Ok(_) => (),
Err(e) => println!("Error wiping registry: {}", e),
}
let hsr_settings =
match Hive::CurrentUser.open(format!("Software\\Cognosphere\\Star Rail"), Security::Write) {
Ok(s) => s,
Err(e) => {
println!("Error getting registry setting: {}", e);
return;
}
};
match hsr_settings.set_value(
"MIHOYOSDK_ADL_PROD_OVERSEA_h1158948810",
&Data::String("".parse().unwrap()),
) {
Ok(_) => (),
Err(e) => println!("Error wiping registry: {}", e),
}
}
#[cfg(windows)]

View File

@@ -107,7 +107,8 @@ pub fn unzip(
.unwrap();
}
if zipfile.contains("GrasscutterQuests") {
// Alternate builds
if zipfile.contains("GrasscutterQuests") || zipfile.contains("Grasscutter50") {
window
.emit("jar_extracted", destpath.to_string() + "grasscutter.jar")
.unwrap();