parent
209b599120
commit
c41a843315
@ -3,8 +3,8 @@ use crate::global::*;
|
|||||||
use crate::http;
|
use crate::http;
|
||||||
use crate::misc;
|
use crate::misc;
|
||||||
|
|
||||||
use std::{fs, path::Path};
|
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
pub fn local_revision(dir: &Path) -> u16 {
|
pub fn local_revision(dir: &Path) -> u16 {
|
||||||
if let Ok(revision) = fs::read_to_string(dir.join(".iw4xrevision")) {
|
if let Ok(revision) = fs::read_to_string(dir.join(".iw4xrevision")) {
|
||||||
@ -26,7 +26,11 @@ pub fn update(dir: &Path) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("[{}] {}", "Downloading".bright_yellow(), dir.join("iw4x.dll").display());
|
println!(
|
||||||
|
"[{}] {}",
|
||||||
|
"Downloading".bright_yellow(),
|
||||||
|
dir.join("iw4x.dll").display()
|
||||||
|
);
|
||||||
http::download_file(
|
http::download_file(
|
||||||
&format!(
|
&format!(
|
||||||
"{}/download/iw4x.dll",
|
"{}/download/iw4x.dll",
|
||||||
|
72
src/main.rs
72
src/main.rs
@ -10,12 +10,12 @@ mod structs;
|
|||||||
use global::*;
|
use global::*;
|
||||||
use structs::*;
|
use structs::*;
|
||||||
|
|
||||||
|
use colored::*;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use mslnk::ShellLink;
|
use mslnk::ShellLink;
|
||||||
use std::{fs, path::Path, path::PathBuf};
|
use std::{borrow::Cow, collections::HashMap, fs, path::Path, path::PathBuf};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use steamlocate::SteamDir;
|
use steamlocate::SteamDir;
|
||||||
use colored::*;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn get_installed_games(games: &Vec<Game>) -> Vec<(u32, PathBuf)> {
|
fn get_installed_games(games: &Vec<Game>) -> Vec<(u32, PathBuf)> {
|
||||||
@ -92,12 +92,15 @@ fn setup_desktop_links(path: &Path, game: &Game) {
|
|||||||
fn auto_install(path: &Path, game: &Game) {
|
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);
|
update(game, path, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn windows_launcher_install(games: &Vec<Game>) {
|
fn windows_launcher_install(games: &Vec<Game>) {
|
||||||
println!("{}", "No game specified/found. Checking for installed Steam games..".yellow());
|
println!(
|
||||||
|
"{}",
|
||||||
|
"No game specified/found. Checking for installed Steam games..".yellow()
|
||||||
|
);
|
||||||
let installed_games = get_installed_games(games);
|
let installed_games = get_installed_games(games);
|
||||||
|
|
||||||
if !installed_games.is_empty() {
|
if !installed_games.is_empty() {
|
||||||
@ -167,13 +170,18 @@ fn prompt_client_selection(games: &[Game]) -> String {
|
|||||||
fn manual_install(games: &[Game]) {
|
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);
|
update(game, &std::env::current_dir().unwrap(), false, false);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_dir(cdn_info: &Vec<CdnFile>, remote_dir: &str, dir: &Path) {
|
fn update_dir(
|
||||||
|
cdn_info: &Vec<CdnFile>,
|
||||||
|
remote_dir: &str,
|
||||||
|
dir: &Path,
|
||||||
|
hashes: &mut HashMap<String, String>,
|
||||||
|
) {
|
||||||
let remote_dir = format!("{}/", remote_dir);
|
let remote_dir = format!("{}/", remote_dir);
|
||||||
|
|
||||||
for file in cdn_info {
|
for file in cdn_info {
|
||||||
@ -181,10 +189,16 @@ fn update_dir(cdn_info: &Vec<CdnFile>, remote_dir: &str, dir: &Path) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_path = dir.join(&file.name.replace(remote_dir.as_str(), ""));
|
let sha1_remote = file.hash.to_lowercase();
|
||||||
|
let file_name = &file.name.replace(remote_dir.as_str(), "");
|
||||||
|
let file_path = dir.join(file_name);
|
||||||
if file_path.exists() {
|
if file_path.exists() {
|
||||||
let sha1_local = misc::get_file_sha1(&file_path).to_lowercase();
|
let sha1_local = hashes
|
||||||
let sha1_remote = file.hash.to_lowercase();
|
.get(file_name)
|
||||||
|
.map(Cow::Borrowed)
|
||||||
|
.unwrap_or_else(|| Cow::Owned(misc::get_file_sha1(&file_path)))
|
||||||
|
.to_string();
|
||||||
|
|
||||||
if sha1_local != sha1_remote {
|
if sha1_local != sha1_remote {
|
||||||
println!(
|
println!(
|
||||||
"[{}] {}",
|
"[{}] {}",
|
||||||
@ -195,25 +209,43 @@ fn update_dir(cdn_info: &Vec<CdnFile>, remote_dir: &str, dir: &Path) {
|
|||||||
} else {
|
} else {
|
||||||
println!("[{}] {}", "Checked".bright_blue(), file_path.display());
|
println!("[{}] {}", "Checked".bright_blue(), file_path.display());
|
||||||
}
|
}
|
||||||
|
hashes.insert(file_name.to_owned(), sha1_remote.to_owned());
|
||||||
} else {
|
} else {
|
||||||
println!("[{}] {}", "Downloading".bright_yellow(), file_path.display());
|
println!(
|
||||||
|
"[{}] {}",
|
||||||
|
"Downloading".bright_yellow(),
|
||||||
|
file_path.display()
|
||||||
|
);
|
||||||
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::download_file(&format!("{}/{}", MASTER, file.name), &file_path);
|
||||||
|
hashes.insert(file_name.to_owned(), sha1_remote.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(game: &Game, dir: &Path, bonus_content: bool) {
|
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(),
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
update_dir(&cdn_info, game.engine, dir);
|
let mut hashes = HashMap::new();
|
||||||
|
let hash_file = dir.join(".sha-sums");
|
||||||
|
if hash_file.exists() && !force {
|
||||||
|
let hash_file = fs::read_to_string(hash_file).unwrap();
|
||||||
|
for line in hash_file.lines() {
|
||||||
|
let mut split = line.split_whitespace();
|
||||||
|
let hash = split.next().unwrap();
|
||||||
|
let file = split.next().unwrap();
|
||||||
|
hashes.insert(file.to_owned(), hash.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_dir(&cdn_info, game.engine, dir, &mut hashes);
|
||||||
|
|
||||||
if game.engine == "iw4" {
|
if game.engine == "iw4" {
|
||||||
iw4x::update(dir);
|
iw4x::update(dir);
|
||||||
@ -221,9 +253,15 @@ fn update(game: &Game, dir: &Path, bonus_content: bool) {
|
|||||||
|
|
||||||
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);
|
update_dir(&cdn_info, bonus, dir, &mut hashes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut hash_file_content = String::new();
|
||||||
|
for (file, hash) in hashes.iter() {
|
||||||
|
hash_file_content.push_str(&format!("{} {}\n", hash, file));
|
||||||
|
}
|
||||||
|
fs::write(dir.join(".sha-sums"), hash_file_content).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn launch(file_path: &PathBuf) {
|
fn launch(file_path: &PathBuf) {
|
||||||
@ -272,6 +310,13 @@ fn main() {
|
|||||||
.map(|e| args.remove(e));
|
.map(|e| args.remove(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.contains(&String::from("force")) {
|
||||||
|
cfg.force_update = true;
|
||||||
|
args.iter()
|
||||||
|
.position(|r| r == "force")
|
||||||
|
.map(|e| args.remove(e));
|
||||||
|
}
|
||||||
|
|
||||||
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());
|
||||||
let games: Vec<Game> = serde_json::from_str(&games_json).unwrap();
|
let games: Vec<Game> = serde_json::from_str(&games_json).unwrap();
|
||||||
|
|
||||||
@ -330,6 +375,7 @@ fn main() {
|
|||||||
g,
|
g,
|
||||||
&std::env::current_dir().unwrap(),
|
&std::env::current_dir().unwrap(),
|
||||||
cfg.download_bonus_content,
|
cfg.download_bonus_content,
|
||||||
|
cfg.force_update,
|
||||||
);
|
);
|
||||||
if !cfg.update_only {
|
if !cfg.update_only {
|
||||||
launch(&PathBuf::from(format!("{}.exe", c)));
|
launch(&PathBuf::from(format!("{}.exe", c)));
|
||||||
|
@ -20,6 +20,7 @@ pub struct Config {
|
|||||||
pub skip_self_update: bool,
|
pub skip_self_update: bool,
|
||||||
pub download_bonus_content: bool,
|
pub download_bonus_content: bool,
|
||||||
pub ask_bonus_content: bool,
|
pub ask_bonus_content: bool,
|
||||||
|
pub force_update: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -29,6 +30,7 @@ impl Default for Config {
|
|||||||
skip_self_update: false,
|
skip_self_update: false,
|
||||||
download_bonus_content: false,
|
download_bonus_content: false,
|
||||||
ask_bonus_content: true,
|
ask_bonus_content: true,
|
||||||
|
force_update: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user