27 Commits

Author SHA1 Message Date
5ed9fd4710 set useragent header 2023-11-07 17:14:40 +01:00
4763759997 Merge pull request #42 from mxve/selfrestart
Selfrestart
2023-11-07 00:20:32 +01:00
6ebb421a7b fix linux 2023-11-06 22:33:58 +01:00
6ef80be01f v0.6.2 2023-11-06 22:27:53 +01:00
1a3c090612 cleanup 2023-11-06 22:27:09 +01:00
fe7c8d2834 self restart 2023-11-06 03:20:46 +01:00
b3168b0a58 don't panic if cleaning up left over files fails 2023-11-06 02:08:29 +01:00
b1cffb44ad v0.6.1 2023-11-06 01:56:49 +01:00
5414213a19 fix existing file hashes always being calculated 2023-11-06 01:56:26 +01:00
6ce845e761 v0.6.0 2023-11-05 17:20:59 +01:00
ecff4846ed improve setup_env on Windows
(real)
935a72e05be1a213a12238f522c8b35f872ecf63
2023-11-04 11:48:04 +01:00
1578924579 lint 2023-11-04 11:35:19 +01:00
33fc7d0f6a import std::env 2023-11-04 07:48:40 +01:00
461eb05ac5 maint(win): improve setup_env on Windows 2023-11-04 07:27:58 +01:00
cb210b16e1 Merge pull request #40 from mxve/async
Async
2023-11-02 16:05:10 +01:00
41ff4acd65 update iw4x first
so we don't have to pass the progressbar to iw4x just to not have it break by a little println
2023-11-02 11:44:08 +01:00
24672aa500 only show filename in pb 2023-11-02 11:31:50 +01:00
05def16ba6 use String::default() for empty strings
as suggested by diamante quality control ™️
2023-11-02 11:27:43 +01:00
c3cda3b845 remove linux i686 2023-11-02 11:05:28 +01:00
3858e743f3 consume 2023-11-02 10:43:36 +01:00
d28fed938c Merge branch 'main' of github.com:mxve/alterware-launcher 2023-11-02 10:40:45 +01:00
ff22c49ced stream files to disk
- Greatly reduced memory usage while downloading
- Added progressbar, download rate
- Added async runtime
- Tweaks to allow usage of async download function
2023-11-02 10:39:58 +01:00
82a1e4ba53 Merge pull request #38 from mxve/dependabot/cargo/serde-1.0.190
Bump serde from 1.0.189 to 1.0.190
2023-10-30 22:00:19 +01:00
de7a661465 Merge pull request #39 from mxve/dependabot/cargo/http_req-0.10.1
Bump http_req from 0.10.0 to 0.10.1
2023-10-30 22:00:07 +01:00
7e8e0fbc97 Bump http_req from 0.10.0 to 0.10.1
Bumps [http_req](https://github.com/jayjamesjay/http_req) from 0.10.0 to 0.10.1.
- [Release notes](https://github.com/jayjamesjay/http_req/releases)
- [Commits](https://github.com/jayjamesjay/http_req/compare/v0.10.0...v0.10.1)

---
updated-dependencies:
- dependency-name: http_req
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 15:31:10 +00:00
b09b92ee7f Bump serde from 1.0.189 to 1.0.190
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.189 to 1.0.190.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.189...v1.0.190)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 15:30:54 +00:00
917640c4e6 dc 2023-10-28 20:14:39 +02:00
9 changed files with 1006 additions and 266 deletions

View File

@ -21,8 +21,6 @@ jobs:
include: include:
- target: x86_64-unknown-linux-gnu - target: x86_64-unknown-linux-gnu
os: ubuntu-20.04 os: ubuntu-20.04
- target: i686-unknown-linux-gnu
os: ubuntu-20.04
- target: x86_64-pc-windows-msvc - target: x86_64-pc-windows-msvc
os: windows-latest os: windows-latest
- target: i686-pc-windows-msvc - target: i686-pc-windows-msvc

1017
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package] [package]
name = "alterware-launcher" name = "alterware-launcher"
version = "0.5.4" version = "0.6.2"
edition = "2021" edition = "2021"
build = "res/build.rs" build = "res/build.rs"
@ -15,16 +15,19 @@ panic = "abort"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
http_req = { version = "0.10.0", default-features = false, features = [ http_req = { version = "0.10.1", default-features = false, features = [
"rust-tls", "rust-tls",
] } ] }
sha1_smol = "1.0.0" sha1_smol = "1.0.0"
serde = { version = "1.0.189", features = ["derive"] } serde = { version = "1.0.190", features = ["derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"
rand = "0.8.5" rand = "0.8.5"
semver = "1.0.20" semver = "1.0.20"
zip = "0.6.6"
colored = "2.0.4" colored = "2.0.4"
reqwest = { version = "0.11.22", features = ["stream"] }
futures-util = "0.3.29"
indicatif = "0.17.7"
tokio = {version="1.33.0", features = ["rt-multi-thread", "macros"]}
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
steamlocate = "2.0.0-alpha.0" steamlocate = "2.0.0-alpha.0"

60
src/http_async.rs Normal file
View File

@ -0,0 +1,60 @@
use std::cmp::min;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use colored::*;
use futures_util::StreamExt;
use indicatif::ProgressBar;
use reqwest::Client;
use crate::misc;
pub async fn download_file(
client: &Client,
pb: &ProgressBar,
url: &str,
path: &PathBuf,
size: u64,
) -> Result<(), String> {
let res = client
.get(url)
.header(
"User-Agent",
&format!(
"AlterWare Launcher | github.com/{}/{}",
crate::global::GH_OWNER,
crate::global::GH_REPO
),
)
.send()
.await
.or(Err(format!("Failed to GET from '{}'", &url)))?;
// Fix for CF shenanigans
let total_size = res.content_length().unwrap_or(size);
pb.set_length(total_size);
pb.println(format!(
"[{}] {} ({})",
"Downloading".bright_yellow(),
misc::cute_path(path),
misc::human_readable_bytes(total_size)
));
pb.set_message(path.file_name().unwrap().to_str().unwrap().to_string());
let mut file =
File::create(path).or(Err(format!("Failed to create file '{}'", path.display())))?;
let mut downloaded: u64 = 0;
let mut stream = res.bytes_stream();
while let Some(item) = stream.next().await {
let chunk = item.or(Err("Error while downloading file"))?;
file.write_all(&chunk)
.or(Err("Error while writing to file"))?;
let new = min(downloaded + (chunk.len() as u64), total_size);
downloaded = new;
pb.set_position(new);
}
pb.set_message(String::default());
Ok(())
}

View File

@ -23,13 +23,21 @@ pub fn update(dir: &Path) {
let local = local_revision(dir); let local = local_revision(dir);
if remote <= local && dir.join("iw4x.dll").exists() { if remote <= local && dir.join("iw4x.dll").exists() {
println!(
"[{}] No files to download for IW4x",
"Info".bright_magenta(),
);
return; return;
} }
println!(
"[{}] Downloading outdated or missing files for IW4x",
"Info".bright_magenta()
);
println!( println!(
"[{}] {}", "[{}] {}",
"Downloading".bright_yellow(), "Downloading".bright_yellow(),
dir.join("iw4x.dll").display() misc::cute_path(&dir.join("iw4x.dll"))
); );
http::download_file( http::download_file(
&format!( &format!(

View File

@ -2,6 +2,7 @@ mod config;
mod github; mod github;
mod global; mod global;
mod http; mod http;
mod http_async;
mod iw4x; mod iw4x;
mod misc; mod misc;
mod self_update; mod self_update;
@ -11,9 +12,10 @@ use global::*;
use structs::*; use structs::*;
use colored::*; use colored::*;
use indicatif::ProgressBar;
#[cfg(windows)] #[cfg(windows)]
use mslnk::ShellLink; use mslnk::ShellLink;
use std::{borrow::Cow, collections::HashMap, fs, path::Path, path::PathBuf}; use std::{borrow::Cow, collections::HashMap, env, fs, path::Path, path::PathBuf};
#[cfg(windows)] #[cfg(windows)]
use steamlocate::SteamDir; use steamlocate::SteamDir;
@ -75,10 +77,7 @@ fn setup_desktop_links(path: &Path, game: &Game) {
let input = misc::stdin().to_ascii_lowercase(); let input = misc::stdin().to_ascii_lowercase();
if input == "y" || input.is_empty() { if input == "y" || input.is_empty() {
let desktop = PathBuf::from(&format!( let desktop = PathBuf::from(&format!("{}\\Desktop", env::var("USERPROFILE").unwrap()));
"{}\\Desktop",
std::env::var("USERPROFILE").unwrap()
));
for c in game.client.iter() { for c in game.client.iter() {
create_shortcut( create_shortcut(
@ -94,14 +93,14 @@ fn setup_desktop_links(path: &Path, game: &Game) {
} }
#[cfg(windows)] #[cfg(windows)]
fn auto_install(path: &Path, game: &Game) { async fn auto_install(path: &Path, game: &Game<'_>) {
setup_client_links(game, path); setup_client_links(game, path);
setup_desktop_links(path, game); setup_desktop_links(path, game);
update(game, path, false, false); update(game, path, false, false).await;
} }
#[cfg(windows)] #[cfg(windows)]
fn windows_launcher_install(games: &Vec<Game>) { async fn windows_launcher_install(games: &Vec<Game<'_>>) {
println!( println!(
"{}", "{}",
"No game specified/found. Checking for installed Steam games..".yellow() "No game specified/found. Checking for installed Steam games..".yellow()
@ -109,13 +108,13 @@ fn windows_launcher_install(games: &Vec<Game>) {
let installed_games = get_installed_games(games); let installed_games = get_installed_games(games);
if !installed_games.is_empty() { if !installed_games.is_empty() {
let current_dir = std::env::current_dir().unwrap(); let current_dir = env::current_dir().unwrap();
for (id, path) in installed_games.iter() { for (id, path) in installed_games.iter() {
if current_dir.starts_with(path) { if current_dir.starts_with(path) {
println!("Found game in current directory."); println!("Found game in current directory.");
println!("Installing AlterWare client for {}.", id); println!("Installing AlterWare client for {}.", id);
let game = games.iter().find(|&g| g.app_id == *id).unwrap(); let game = games.iter().find(|&g| g.app_id == *id).unwrap();
auto_install(path, game); auto_install(path, game).await;
println!("Installation complete. Please run the launcher again or use a shortcut to launch the game."); println!("Installation complete. Please run the launcher again or use a shortcut to launch the game.");
std::io::stdin().read_line(&mut String::new()).unwrap(); std::io::stdin().read_line(&mut String::new()).unwrap();
std::process::exit(0); std::process::exit(0);
@ -132,21 +131,21 @@ fn windows_launcher_install(games: &Vec<Game>) {
let input: u32 = misc::stdin().parse().unwrap(); let input: u32 = misc::stdin().parse().unwrap();
if input == 0 { if input == 0 {
return manual_install(games); return manual_install(games).await;
} }
for (id, path) in installed_games.iter() { for (id, path) in installed_games.iter() {
if *id == input { if *id == input {
let game = games.iter().find(|&g| g.app_id == input).unwrap(); let game = games.iter().find(|&g| g.app_id == input).unwrap();
let launcher_path = std::env::current_exe().unwrap(); let launcher_path = env::current_exe().unwrap();
let target_path = path.join("alterware-launcher.exe"); let target_path = path.join("alterware-launcher.exe");
if launcher_path != target_path { if launcher_path != target_path {
fs::copy(launcher_path, target_path).unwrap(); fs::copy(launcher_path, target_path).unwrap();
println!("Launcher copied to {}", path.display()); println!("Launcher copied to {}", path.display());
} }
auto_install(path, game); auto_install(path, game).await;
println!("Installation complete. Please run the launcher again or use a shortcut to launch the game."); println!("Installation complete. Please run the launcher again or use a shortcut to launch the game.");
std::io::stdin().read_line(&mut String::new()).unwrap(); std::io::stdin().read_line(&mut String::new()).unwrap();
break; break;
@ -154,7 +153,7 @@ fn windows_launcher_install(games: &Vec<Game>) {
} }
std::process::exit(0); std::process::exit(0);
} else { } else {
manual_install(games); manual_install(games).await;
} }
} }
@ -171,10 +170,10 @@ fn prompt_client_selection(games: &[Game]) -> String {
String::from(games[input].client[0]) String::from(games[input].client[0])
} }
fn manual_install(games: &[Game]) { async fn manual_install(games: &[Game<'_>]) {
let selection = prompt_client_selection(games); let selection = prompt_client_selection(games);
let game = games.iter().find(|&g| g.client[0] == selection).unwrap(); let game = games.iter().find(|&g| g.client[0] == selection).unwrap();
update(game, &std::env::current_dir().unwrap(), false, false); update(game, &env::current_dir().unwrap(), false, false).await;
println!("Installation complete. Please run the launcher again or use a shortcut to launch the game."); println!("Installation complete. Please run the launcher again or use a shortcut to launch the game.");
std::io::stdin().read_line(&mut String::new()).unwrap(); std::io::stdin().read_line(&mut String::new()).unwrap();
std::process::exit(0); std::process::exit(0);
@ -192,12 +191,15 @@ fn total_download_size(cdn_info: &Vec<CdnFile>, remote_dir: &str) -> u64 {
size size
} }
fn update_dir( async fn update_dir(
cdn_info: &Vec<CdnFile>, cdn_info: &Vec<CdnFile>,
remote_dir: &str, remote_dir: &str,
dir: &Path, dir: &Path,
hashes: &mut HashMap<String, String>, hashes: &mut HashMap<String, String>,
pb: &ProgressBar,
) { ) {
misc::pb_style_download(pb, false);
let remote_dir_pre = format!("{}/", remote_dir); let remote_dir_pre = format!("{}/", remote_dir);
let mut files_to_download: Vec<CdnFile> = vec![]; let mut files_to_download: Vec<CdnFile> = vec![];
@ -220,7 +222,12 @@ fn update_dir(
if sha1_local != sha1_remote { if sha1_local != sha1_remote {
files_to_download.push(file.clone()); files_to_download.push(file.clone());
} else { } else {
println!("[{}] {}", "Checked".bright_blue(), file_path.display()); pb.println(format!(
"[{}] {}",
"Checked".bright_blue(),
misc::cute_path(&file_path)
));
hashes.insert(file_name.to_owned(), file.hash.to_lowercase());
} }
} else { } else {
files_to_download.push(file.clone()); files_to_download.push(file.clone());
@ -228,39 +235,45 @@ fn update_dir(
} }
if files_to_download.is_empty() { if files_to_download.is_empty() {
println!( pb.println(format!(
"[{}] No files to download for {}", "[{}] No files to download for {}",
"Info".bright_magenta(), "Info".bright_magenta(),
remote_dir remote_dir
); ));
return; return;
} }
println!( pb.println(format!(
"[{}] Downloading outdated or missing files for {}, {}", "[{}] Downloading outdated or missing files for {}, {}",
"Info".bright_magenta(), "Info".bright_magenta(),
remote_dir, remote_dir,
misc::human_readable_bytes(total_download_size(&files_to_download, remote_dir)) misc::human_readable_bytes(total_download_size(&files_to_download, remote_dir))
); ));
misc::pb_style_download(pb, true);
let client = reqwest::Client::new();
for file in files_to_download { for file in files_to_download {
let file_name = &file.name.replace(&remote_dir_pre, ""); let file_name = &file.name.replace(&remote_dir_pre, "");
let file_path = dir.join(file_name); let file_path = dir.join(file_name);
println!(
"[{}] {} ({})",
"Downloading".bright_yellow(),
file_path.display(),
misc::human_readable_bytes(file.size as u64)
);
if let Some(parent) = file_path.parent() { if let Some(parent) = file_path.parent() {
if !parent.exists() { if !parent.exists() {
fs::create_dir_all(parent).unwrap(); fs::create_dir_all(parent).unwrap();
} }
} }
http::download_file(&format!("{}/{}", MASTER, file.name), &file_path); http_async::download_file(
&client,
pb,
&format!("{}/{}", MASTER, file.name),
&file_path,
file.size as u64,
)
.await
.unwrap();
hashes.insert(file_name.to_owned(), file.hash.to_lowercase()); hashes.insert(file_name.to_owned(), file.hash.to_lowercase());
} }
misc::pb_style_download(pb, false);
} }
fn update(game: &Game, dir: &Path, bonus_content: bool, force: bool) { async fn update(game: &Game<'_>, dir: &Path, bonus_content: bool, force: bool) {
let cdn_info: Vec<CdnFile> = serde_json::from_str(&http::get_body_string( let cdn_info: Vec<CdnFile> = serde_json::from_str(&http::get_body_string(
format!("{}/files.json", MASTER).as_str(), format!("{}/files.json", MASTER).as_str(),
)) ))
@ -278,18 +291,21 @@ fn update(game: &Game, dir: &Path, bonus_content: bool, force: bool) {
} }
} }
update_dir(&cdn_info, game.engine, dir, &mut hashes);
if game.engine == "iw4" { if game.engine == "iw4" {
iw4x::update(dir); iw4x::update(dir);
} }
let pb = ProgressBar::new(0);
update_dir(&cdn_info, game.engine, dir, &mut hashes, &pb).await;
if bonus_content && !game.bonus.is_empty() { if bonus_content && !game.bonus.is_empty() {
for bonus in game.bonus.iter() { for bonus in game.bonus.iter() {
update_dir(&cdn_info, bonus, dir, &mut hashes); update_dir(&cdn_info, bonus, dir, &mut hashes, &pb).await;
} }
} }
pb.finish();
let mut hash_file_content = String::new(); let mut hash_file_content = String::new();
for (file, hash) in hashes.iter() { for (file, hash) in hashes.iter() {
hash_file_content.push_str(&format!("{} {}\n", hash, file)); hash_file_content.push_str(&format!("{} {}\n", hash, file));
@ -298,6 +314,7 @@ fn update(game: &Game, dir: &Path, bonus_content: bool, force: bool) {
} }
fn launch(file_path: &PathBuf, args: &str) { fn launch(file_path: &PathBuf, args: &str) {
println!("\n\nJoin the AlterWare Discord server:\nhttps://discord.gg/2ETE8engZM\n\n");
println!("Launching {} {}", file_path.display(), args); println!("Launching {} {}", file_path.display(), args);
std::process::Command::new(file_path) std::process::Command::new(file_path)
.args(args.trim().split(' ')) .args(args.trim().split(' '))
@ -314,6 +331,22 @@ fn setup_env() {
println!("{:#?}", error); println!("{:#?}", error);
colored::control::SHOULD_COLORIZE.set_override(false); colored::control::SHOULD_COLORIZE.set_override(false);
}); });
if let Ok(system_root) = env::var("SystemRoot") {
if let Ok(current_dir) = env::current_dir() {
if current_dir.starts_with(system_root) {
if let Ok(current_exe) = env::current_exe() {
if let Some(parent) = current_exe.parent() {
if let Err(error) = env::set_current_dir(parent) {
eprintln!("{:#?}", error);
} else {
println!("Running from the system directory. Changed working directory to the executable location.");
}
}
}
}
}
}
} }
fn arg_value(args: &[String], arg: &str) -> Option<String> { fn arg_value(args: &[String], arg: &str) -> Option<String> {
@ -337,11 +370,11 @@ fn arg_remove_value(args: &mut Vec<String>, arg: &str) {
}; };
} }
fn main() { #[tokio::main]
async fn main() {
#[cfg(windows)] #[cfg(windows)]
setup_env(); setup_env();
let mut args: Vec<String> = env::args().collect();
let mut args: Vec<String> = std::env::args().collect();
if arg_bool(&args, "--help") { if arg_bool(&args, "--help") {
println!("CLI Args:"); println!("CLI Args:");
@ -388,7 +421,7 @@ fn main() {
install_path = PathBuf::from(path); install_path = PathBuf::from(path);
arg_remove_value(&mut args, "-p"); arg_remove_value(&mut args, "-p");
} else { } else {
install_path = std::env::current_dir().unwrap(); install_path = env::current_dir().unwrap();
} }
let mut cfg = config::load(install_path.join("alterware-launcher.json")); let mut cfg = config::load(install_path.join("alterware-launcher.json"));
@ -421,7 +454,7 @@ fn main() {
cfg.args = pass; cfg.args = pass;
arg_remove_value(&mut args, "--pass"); arg_remove_value(&mut args, "--pass");
} else if cfg.args.is_empty() { } else if cfg.args.is_empty() {
cfg.args = String::from(""); cfg.args = String::default();
} }
let games_json = http::get_body_string(format!("{}/games.json", MASTER).as_str()); let games_json = http::get_body_string(format!("{}/games.json", MASTER).as_str());
@ -441,7 +474,7 @@ fn main() {
} }
#[cfg(windows)] #[cfg(windows)]
setup_client_links(g, &std::env::current_dir().unwrap()); setup_client_links(g, &env::current_dir().unwrap());
#[cfg(not(windows))] #[cfg(not(windows))]
println!("Multiple clients installed, set the client as the first argument to launch a specific client."); println!("Multiple clients installed, set the client as the first argument to launch a specific client.");
@ -483,7 +516,8 @@ fn main() {
install_path.as_path(), install_path.as_path(),
cfg.download_bonus_content, cfg.download_bonus_content,
cfg.force_update, cfg.force_update,
); )
.await;
if !cfg.update_only { if !cfg.update_only {
launch(&install_path.join(format!("{}.exe", c)), &cfg.args); launch(&install_path.join(format!("{}.exe", c)), &cfg.args);
} }
@ -493,10 +527,10 @@ fn main() {
} }
#[cfg(windows)] #[cfg(windows)]
windows_launcher_install(&games); windows_launcher_install(&games).await;
#[cfg(not(windows))] #[cfg(not(windows))]
manual_install(&games); manual_install(&games).await;
println!("{}", "Game not found!".bright_red()); println!("{}", "Game not found!".bright_red());
println!("Place the launcher in the game folder, if that doesn't work specify the client on the command line (ex. alterware-launcher.exe iw4-sp)"); println!("Place the launcher in the game folder, if that doesn't work specify the client on the command line (ex. alterware-launcher.exe iw4-sp)");

View File

@ -1,6 +1,10 @@
use std::{fs, path::PathBuf}; use std::{
fs,
path::{Path, PathBuf},
};
use colored::Colorize; use colored::Colorize;
use indicatif::{ProgressBar, ProgressStyle};
pub fn get_file_sha1(path: &PathBuf) -> String { pub fn get_file_sha1(path: &PathBuf) -> String {
let mut sha1 = sha1_smol::Sha1::new(); let mut sha1 = sha1_smol::Sha1::new();
@ -35,5 +39,20 @@ pub fn human_readable_bytes(bytes: u64) -> String {
bytes /= 1024.0; bytes /= 1024.0;
i += 1; i += 1;
} }
format!("{:.2} {}", bytes, units[i]) format!("{:.2}{}", bytes, units[i])
}
pub fn pb_style_download(pb: &ProgressBar, state: bool) {
if state {
pb.set_style(
ProgressStyle::with_template("{spinner:.magenta} {msg:.magenta} > {bytes}/{total_bytes} | {bytes_per_sec} | {eta}")
.unwrap(),
);
} else {
pb.set_style(ProgressStyle::with_template("{spinner:.magenta} {msg}").unwrap());
}
}
pub fn cute_path(path: &Path) -> String {
path.to_str().unwrap().replace('\\', "/")
} }

View File

@ -25,6 +25,19 @@ pub fn run(_update_only: bool) {
} }
} }
#[cfg(windows)]
pub fn restart() -> std::io::Error {
use std::os::windows::process::CommandExt;
match std::process::Command::new(std::env::current_exe().unwrap())
.args(std::env::args().skip(1))
.creation_flags(0x00000010) // CREATE_NEW_CONSOLE
.spawn()
{
Ok(_) => std::process::exit(0),
Err(err) => err,
}
}
#[cfg(windows)] #[cfg(windows)]
pub fn run(update_only: bool) { pub fn run(update_only: bool) {
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
@ -43,7 +56,9 @@ pub fn run(update_only: bool) {
&& (file_name.contains(".__relocated__.exe") && (file_name.contains(".__relocated__.exe")
|| file_name.contains(".__selfdelete__.exe")) || file_name.contains(".__selfdelete__.exe"))
{ {
fs::remove_file(file.path()).unwrap(); fs::remove_file(file.path()).unwrap_or_else(|_| {
println!("Failed to remove old launcher file.");
});
} }
} }
@ -66,7 +81,7 @@ pub fn run(update_only: bool) {
} else { } else {
"alterware-launcher.exe" "alterware-launcher.exe"
}; };
println!("{}", launcher_name);
http::download_file( http::download_file(
&format!( &format!(
"{}/download/{}", "{}/download/{}",
@ -83,12 +98,12 @@ pub fn run(update_only: bool) {
self_replace::self_replace("alterware-launcher-update.exe").unwrap(); self_replace::self_replace("alterware-launcher-update.exe").unwrap();
fs::remove_file(&file_path).unwrap(); fs::remove_file(&file_path).unwrap();
println!(
"Launcher updated. View the changelog at https://github.com/{}/{}/releases/latest", // restarting spawns a new console, automation should manually restart on exit code 201
GH_OWNER, GH_REPO,
);
println!("Please restart the launcher.");
if !update_only { if !update_only {
let restart_error = restart().to_string();
println!("Failed to restart launcher: {}", restart_error);
println!("Please restart the launcher manually.");
misc::stdin(); misc::stdin();
} }
std::process::exit(201); std::process::exit(201);

View File

@ -32,7 +32,7 @@ impl Default for Config {
download_bonus_content: false, download_bonus_content: false,
ask_bonus_content: true, ask_bonus_content: true,
force_update: false, force_update: false,
args: String::from(""), args: String::default(),
} }
} }
} }