First commit

This commit is contained in:
Tipragot 2023-11-18 22:51:55 +01:00
commit 06a8fcd807
8 changed files with 1618 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

1434
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

14
Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "launcher"
version = "0.1.0"
edition = "2021"
build = "build.rs"
[dependencies]
anyhow = "1.0.75"
glob = "0.3.1"
reqwest = { version = "0.11.22", features = ["blocking"] }
zip = "0.6.6"
[build-dependencies]
winres = "0.1.12"

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# Launcher
Le code est moche et pas commenté mais tkt j'ai fais ça en une soirée j'avais la fleme

7
build.rs Normal file
View file

@ -0,0 +1,7 @@
fn main() {
if cfg!(target_os = "windows") {
let mut res = winres::WindowsResource::new();
res.set_icon("icon.ico");
res.compile().unwrap();
}
}

BIN
icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

100
src/lib.rs Normal file
View file

@ -0,0 +1,100 @@
use anyhow::Context;
use reqwest::{blocking::Client, Method};
use std::{
fs::{self, File},
io,
};
use reqwest::Url;
use zip::ZipArchive;
fn get_remote_size(name: &str) -> anyhow::Result<u64> {
Ok(Client::new()
.execute(reqwest::blocking::Request::new(
Method::HEAD,
Url::parse(&format!("https://tipragot.fr/paimon/{name}.zip"))?,
))?
.headers()
.get("content-length")
.context("failed to get content-length")?
.to_str()?
.parse()?)
}
pub fn download(name: &str) -> anyhow::Result<()> {
let file_size = get_remote_size(name)?;
if let Ok(metadata) = fs::metadata(format!("downloads/{name}.zip")) {
if metadata.len() == file_size {
return Ok(());
}
}
println!("Downloading {name} ({} Mo)", file_size / 1000000);
fs::create_dir_all("downloads")?;
reqwest::blocking::get(format!("https://tipragot.fr/paimon/{name}.zip"))?
.error_for_status()?
.copy_to(&mut File::create(format!("downloads/{name}.zip"))?)?;
Ok(())
}
pub fn apply_zip(name: &str) -> anyhow::Result<()> {
// Open the archive
let mut archive = ZipArchive::new(File::open(format!("downloads/{name}.zip"))?)?;
// Get all folders in the archive
let mut exact_folders = Vec::new();
for i in 0..archive.len() {
let zip_file = archive.by_index(i)?;
if zip_file.is_dir() && zip_file.comment() == "exact" {
exact_folders.push(zip_file.name().to_owned());
}
}
// Extract files
let mut exact_files = Vec::new();
for i in 0..archive.len() {
let mut zip_file = archive.by_index(i)?;
if zip_file.is_dir() {
continue;
}
let path = zip_file
.enclosed_name()
.context("invalid filename")?
.to_owned();
for exact_folder in &exact_folders {
if path.starts_with(exact_folder) {
exact_files.push(path.clone());
break;
}
}
// Check if the file is already up to date
if let Ok(metadata) = fs::metadata(&path) {
if zip_file.comment() == "once" || metadata.len() == zip_file.size() {
continue;
}
}
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let mut out_file = File::create(&path)?;
io::copy(&mut zip_file, &mut out_file)?;
}
// Remove orphan files
for exact_folder in exact_folders {
for file in glob::glob(&format!("{exact_folder}/**/*"))? {
let file = file?;
if file.is_dir() {
continue;
}
if !exact_files.contains(&file) {
fs::remove_file(file)?;
}
}
}
Ok(())
}

59
src/main.rs Normal file
View file

@ -0,0 +1,59 @@
use launcher::{apply_zip, download};
use std::env;
use std::io::Write;
use std::path::Path;
use std::{env::set_current_dir, fs, io, process::Command};
fn main() -> anyhow::Result<()> {
// Move to the project directory
let project_folder = Path::new(&env::var("APPDATA")?).join(".paimon");
fs::create_dir_all(&project_folder)?;
set_current_dir(project_folder)?;
// Get the player username
let username = match fs::read_to_string("username.txt") {
Ok(username) => username,
Err(_) => {
print!("Enter your username: ");
io::stdout().flush()?;
let mut username = String::new();
io::stdin().read_line(&mut username)?;
fs::write("username.txt", username.trim())?;
username
}
};
// Download all the zip files
download("runtime")?;
download("libraries")?;
download("assets")?;
download("config")?;
download("mods")?;
// Apply all the zip files
println!("Updating...");
apply_zip("runtime")?;
apply_zip("libraries")?;
apply_zip("assets")?;
apply_zip("config")?;
apply_zip("mods")?;
// Launch the game
println!("Launching game...");
set_current_dir("data/game")?;
Command::new("../runtime/bin/java.exe")
.args([
"-cp",
"../libraries/*",
"net.fabricmc.loader.impl.launch.knot.KnotClient",
"--assetsDir",
"../assets",
"--assetIndex",
"5",
"--username",
username.trim(),
])
.status()?;
Ok(())
}