mirror of
https://github.com/alterware/alterware-launcher.git
synced 2025-12-05 15:57:50 +00:00
Compare commits
1 Commits
v0.11.3
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2432f57ef |
71
Cargo.lock
generated
71
Cargo.lock
generated
@@ -19,7 +19,7 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "alterware-launcher"
|
||||
version = "0.11.3"
|
||||
version = "0.11.1"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"colored",
|
||||
@@ -304,27 +304,6 @@ dependencies = [
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
@@ -561,6 +540,15 @@ version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.2.0"
|
||||
@@ -808,16 +796,6 @@ version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.14"
|
||||
@@ -1023,12 +1001,6 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
@@ -1228,17 +1200,6 @@ dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||
dependencies = [
|
||||
"getrandom 0.2.10",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.20"
|
||||
@@ -1600,12 +1561,12 @@ checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
|
||||
|
||||
[[package]]
|
||||
name = "steamlocate"
|
||||
version = "2.0.0-beta.2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3b6a4810c4e7fecb0123a9a8ba99b335c17d92e636c265ef99108ee4734c812"
|
||||
checksum = "a13160bc6ea5cd80cde195ad4a4c629701db2bf397b62c139aa9e739016d2499"
|
||||
dependencies = [
|
||||
"crc",
|
||||
"dirs",
|
||||
"home",
|
||||
"keyvalues-parser",
|
||||
"keyvalues-serde",
|
||||
"serde",
|
||||
@@ -2437,12 +2398,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.51.0"
|
||||
version = "0.55.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc"
|
||||
checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "alterware-launcher"
|
||||
version = "0.11.3"
|
||||
version = "0.11.1"
|
||||
edition = "2021"
|
||||
build = "res/build.rs"
|
||||
|
||||
@@ -31,7 +31,7 @@ openssl = { version = "0.10", default-features = false, features = ["vendored"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
# todo: update to 2.0.x; needs testing on windows
|
||||
steamlocate = "=2.0.0-beta.2"
|
||||
steamlocate = "=2.0.1"
|
||||
mslnk = "0.1"
|
||||
self-replace = "1.5"
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn save_cache(dir: &Path, cache: Cache) {
|
||||
let cache_path = dir.join("awcache.json");
|
||||
let cache_serialized = serde_json::to_string_pretty(&cache).unwrap();
|
||||
fs::write(cache_path, cache_serialized).unwrap_or_else(|e| {
|
||||
error!("Failed to save cache: {e}");
|
||||
error!("Failed to save cache: {}", e);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ pub async fn rate_cdns_and_display() {
|
||||
"Unknown".bright_red()
|
||||
);
|
||||
} else {
|
||||
println!("User region: {user_region:?}");
|
||||
println!("User region: {:?}", user_region);
|
||||
}
|
||||
|
||||
println!("Rating CDNs...");
|
||||
|
||||
@@ -17,13 +17,17 @@ pub async fn latest_tag_full(
|
||||
repo: &str,
|
||||
) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let github_body = crate::http_async::get_body_string(
|
||||
format!("https://api.github.com/repos/{owner}/{repo}/releases/latest").as_str(),
|
||||
format!(
|
||||
"https://api.github.com/repos/{}/{}/releases/latest",
|
||||
owner, repo
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to fetch GitHub API: {e}"))?;
|
||||
.map_err(|e| format!("Failed to fetch GitHub API: {}", e))?;
|
||||
|
||||
let github_json: serde_json::Value = serde_json::from_str(&github_body)
|
||||
.map_err(|e| format!("Failed to parse GitHub API response: {e}"))?;
|
||||
.map_err(|e| format!("Failed to parse GitHub API response: {}", e))?;
|
||||
|
||||
let tag_name = github_json
|
||||
.get("tag_name")
|
||||
@@ -39,13 +43,13 @@ pub async fn latest_tag_prerelease(
|
||||
repo: &str,
|
||||
) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let github_body = crate::http_async::get_body_string(
|
||||
format!("https://api.github.com/repos/{owner}/{repo}/releases").as_str(),
|
||||
format!("https://api.github.com/repos/{}/{}/releases", owner, repo).as_str(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to fetch GitHub API: {e}"))?;
|
||||
.map_err(|e| format!("Failed to fetch GitHub API: {}", e))?;
|
||||
|
||||
let github_json: serde_json::Value = serde_json::from_str(&github_body)
|
||||
.map_err(|e| format!("Failed to parse GitHub API response: {e}"))?;
|
||||
.map_err(|e| format!("Failed to parse GitHub API response: {}", e))?;
|
||||
|
||||
let latest_release = github_json.get(0).ok_or("No releases found")?;
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ use crate::cdn::{Hosts, Region, Server};
|
||||
|
||||
pub const GH_OWNER: &str = "alterware";
|
||||
pub const GH_REPO: &str = "alterware-launcher";
|
||||
pub const GH_IW4X_OWNER: &str = "iw4x";
|
||||
pub const GH_IW4X_REPO: &str = "iw4x-client";
|
||||
pub const DEFAULT_MASTER: &str = "https://cdn.alterware.ovh";
|
||||
|
||||
pub const CDN_HOSTS: [Server; 2] = [
|
||||
|
||||
46
src/iw4x.rs
Normal file
46
src/iw4x.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use crate::extend::*;
|
||||
use crate::github;
|
||||
use crate::global::*;
|
||||
use crate::http_async;
|
||||
use crate::misc;
|
||||
use crate::structs;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
pub async fn remote_revision(prerelease: Option<bool>) -> u16 {
|
||||
match github::latest_tag(GH_IW4X_OWNER, GH_IW4X_REPO, prerelease).await {
|
||||
Ok(tag) => misc::rev_to_int(&tag),
|
||||
Err(_) => {
|
||||
crate::println_error!("Failed to get latest version for {GH_IW4X_OWNER}/{GH_IW4X_REPO}, assuming we are up to date.");
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update(dir: &Path, cache: &mut structs::Cache, prerelease: Option<bool>) {
|
||||
let remote = remote_revision(prerelease).await;
|
||||
let local = misc::rev_to_int(&cache.iw4x_revision);
|
||||
|
||||
if remote <= local && dir.join("iw4x.dll").exists() {
|
||||
crate::println_info!("No files to download for IW4x");
|
||||
return;
|
||||
}
|
||||
|
||||
crate::println_info!("Downloading outdated or missing files for IW4x",);
|
||||
println!(
|
||||
"{}{}",
|
||||
misc::prefix("downloading"),
|
||||
dir.join("iw4x.dll").cute_path()
|
||||
);
|
||||
http_async::download_file(
|
||||
&format!(
|
||||
"{}/iw4x.dll",
|
||||
github::download_url(GH_IW4X_OWNER, GH_IW4X_REPO, Some(&format!("r{remote}")))
|
||||
),
|
||||
&dir.join("iw4x.dll"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cache.iw4x_revision = format!("r{remote}");
|
||||
}
|
||||
101
src/main.rs
101
src/main.rs
@@ -6,6 +6,7 @@ mod github;
|
||||
mod global;
|
||||
mod http;
|
||||
mod http_async;
|
||||
mod iw4x;
|
||||
mod misc;
|
||||
mod self_update;
|
||||
mod structs;
|
||||
@@ -27,7 +28,7 @@ use mslnk::ShellLink;
|
||||
use simple_log::LogConfigBuilder;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
collections::{HashMap, HashSet},
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
@@ -116,7 +117,7 @@ fn setup_desktop_links(path: &Path, game: &Game) {
|
||||
async fn auto_install(path: &Path, game: &Game<'_>) {
|
||||
setup_client_links(game, path);
|
||||
setup_desktop_links(path, game);
|
||||
update(game, path, false, false, None).await;
|
||||
update(game, path, false, false, None, None, None).await;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -186,7 +187,7 @@ fn total_download_size(cdn_info: &Vec<CdnFile>, remote_dir: &str) -> u64 {
|
||||
let remote_dir = format!("{remote_dir}/");
|
||||
let mut size: u64 = 0;
|
||||
for file in cdn_info {
|
||||
if !file.name.starts_with(&remote_dir) {
|
||||
if !file.name.starts_with(&remote_dir) || file.name == "iw4/iw4x.dll" {
|
||||
continue;
|
||||
}
|
||||
size += file.size as u64;
|
||||
@@ -200,6 +201,7 @@ async fn update_dir(
|
||||
dir: &Path,
|
||||
hashes: &mut HashMap<String, String>,
|
||||
pb: &ProgressBar,
|
||||
skip_iw4x_sp: bool,
|
||||
) {
|
||||
misc::pb_style_download(pb, false);
|
||||
|
||||
@@ -208,7 +210,10 @@ async fn update_dir(
|
||||
let mut files_to_download: Vec<CdnFile> = vec![];
|
||||
|
||||
for file in cdn_info {
|
||||
if !file.name.starts_with(&remote_dir_pre) {
|
||||
if !file.name.starts_with(&remote_dir_pre) || file.name == "iw4/iw4x.dll" {
|
||||
continue;
|
||||
}
|
||||
if skip_iw4x_sp && file.name == "iw4/iw4x-sp.exe" {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -332,12 +337,15 @@ async fn update(
|
||||
dir: &Path,
|
||||
bonus_content: bool,
|
||||
force: bool,
|
||||
skip_iw4x_sp: Option<bool>,
|
||||
ignore_required_files: Option<bool>,
|
||||
prerelease: Option<bool>,
|
||||
) {
|
||||
info!("Starting update for game engine: {}", game.engine);
|
||||
info!("Update path: {}", dir.display());
|
||||
debug!("Bonus content: {}, Force update: {}", bonus_content, force);
|
||||
|
||||
let skip_iw4x_sp = skip_iw4x_sp.unwrap_or(false);
|
||||
let ignore_required_files = ignore_required_files.unwrap_or(false);
|
||||
|
||||
let res =
|
||||
@@ -397,12 +405,66 @@ async fn update(
|
||||
}
|
||||
}
|
||||
|
||||
if game.engine == "iw4" {
|
||||
iw4x::update(dir, &mut cache, prerelease).await;
|
||||
|
||||
let scan_dirs = ["iw4x", "zone/patch"];
|
||||
let valid_files: HashSet<_> = cdn_info
|
||||
.iter()
|
||||
.filter_map(|cdn_file| {
|
||||
if cdn_file.name.starts_with("iw4/") || cdn_file.name.starts_with("iw4-dlc/") {
|
||||
Some(Path::new(&cdn_file.name).to_path_buf())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
for scan_dir in scan_dirs.iter() {
|
||||
let full_scan_dir = dir.join(scan_dir);
|
||||
if !full_scan_dir.exists() || !full_scan_dir.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
for entry in walkdir::WalkDir::new(&full_scan_dir)
|
||||
.into_iter()
|
||||
.filter_map(Result::ok)
|
||||
.filter(|e| e.file_type().is_file())
|
||||
{
|
||||
let rel_path = entry.path().strip_prefix(dir).unwrap_or(entry.path());
|
||||
let cdn_paths = [
|
||||
Path::new("iw4").join(rel_path),
|
||||
Path::new("iw4-dlc").join(rel_path),
|
||||
];
|
||||
|
||||
if !cdn_paths.iter().any(|path| valid_files.contains(path)) {
|
||||
crate::println_info!("{}{}", misc::prefix("removed"), entry.path().cute_path());
|
||||
if std::fs::remove_file(entry.path()).is_err() {
|
||||
crate::println_error!(
|
||||
"{}Couldn't delete {}",
|
||||
misc::prefix("error"),
|
||||
entry.path().cute_path()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let pb = ProgressBar::new(0);
|
||||
update_dir(&cdn_info, game.engine, dir, &mut cache.hashes, &pb).await;
|
||||
update_dir(
|
||||
&cdn_info,
|
||||
game.engine,
|
||||
dir,
|
||||
&mut cache.hashes,
|
||||
&pb,
|
||||
skip_iw4x_sp,
|
||||
)
|
||||
.await;
|
||||
|
||||
if bonus_content && !game.bonus.is_empty() {
|
||||
for bonus in game.bonus.iter() {
|
||||
update_dir(&cdn_info, bonus, dir, &mut cache.hashes, &pb).await;
|
||||
update_dir(&cdn_info, bonus, dir, &mut cache.hashes, &pb, skip_iw4x_sp).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,18 +549,9 @@ 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");
|
||||
crate::println_info!("Launching {} {args}", file_path.display());
|
||||
|
||||
let launcher = if misc::is_program_in_path("umu-run") {
|
||||
Some("umu-run")
|
||||
} else if misc::is_program_in_path("wine") {
|
||||
Some("wine")
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let exit_status = if let Some(launcher) = launcher {
|
||||
println!("Found {launcher}, launching game using {launcher}.\nIf you run into issues or want to launch a different way, run {} manually.", file_path.display());
|
||||
std::process::Command::new(launcher)
|
||||
let exit_status = if misc::is_program_in_path("wine") {
|
||||
println!("Found wine, launching game using wine.\nIf you run into issues or want to launch a different way, run {} manually.", file_path.display());
|
||||
std::process::Command::new("wine")
|
||||
.args([file_path.to_str().unwrap(), args.trim()])
|
||||
.current_dir(file_path.parent().unwrap())
|
||||
.spawn()
|
||||
@@ -574,7 +627,7 @@ fn show_iw4x_info() {
|
||||
"{}",
|
||||
"IW4x is not provided through AlterWare anymore.".bright_red()
|
||||
);
|
||||
println!("Please visit https://aka.alterware.dev/iw4x for more information");
|
||||
println!("Please use iw4x-launcher.exe instead or visit www.iw4x.dev/install");
|
||||
misc::stdin();
|
||||
std::process::exit(0);
|
||||
}
|
||||
@@ -891,6 +944,14 @@ async fn main() {
|
||||
"engine",
|
||||
cfg.engine.clone(),
|
||||
);
|
||||
if cfg.engine == "iw4" && cfg.args.is_empty() {
|
||||
cfg.args = String::from("-stdout");
|
||||
config::save_value_s(
|
||||
install_path.join("alterware-launcher.json"),
|
||||
"args",
|
||||
cfg.args.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
if !cfg.skip_redist {
|
||||
@@ -919,7 +980,9 @@ async fn main() {
|
||||
install_path.as_path(),
|
||||
cfg.download_bonus_content,
|
||||
cfg.force_update,
|
||||
Some(&game != "iw4x-sp"),
|
||||
Some(ignore_required_files),
|
||||
Some(cfg.prerelease),
|
||||
)
|
||||
.await;
|
||||
if !cfg.update_only {
|
||||
|
||||
@@ -12,6 +12,13 @@ pub fn stdin() -> String {
|
||||
input.trim().to_string()
|
||||
}
|
||||
|
||||
pub fn rev_to_int(rev: &str) -> u16 {
|
||||
rev.strip_prefix('r')
|
||||
.unwrap_or("0")
|
||||
.parse::<u16>()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn human_readable_bytes(bytes: u64) -> String {
|
||||
let mut bytes = bytes as f64;
|
||||
let mut i = 0;
|
||||
|
||||
Reference in New Issue
Block a user