Skip to content

Commit

Permalink
refactor: whole launch base + bump v0.2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
1zun4 committed Mar 30, 2024
1 parent 1bade18 commit affa1c7
Show file tree
Hide file tree
Showing 21 changed files with 982 additions and 539 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "liquidlauncher",
"private": true,
"version": "0.2.5",
"version": "0.2.6",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "liquidlauncher"
version = "0.2.5"
version = "0.2.6"
description = "A LiquidBounce launcher for Minecraft, written in Rust using Tauri."
authors = ["1zuna <[email protected]>", "superblaubeere27"]
license = "GNU General Public License v3.0"
Expand Down
62 changes: 37 additions & 25 deletions src-tauri/src/app/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ use crate::utils::percentage_of_total_memory;

use super::{api::{ApiEndpoints, Build, LoaderMod, ModSource}, app_data::LauncherOptions};

pub type ShareableWindow = Arc<Mutex<Window>>;

struct RunnerInstance {
terminator: tokio::sync::oneshot::Sender<()>,
}
Expand Down Expand Up @@ -204,15 +206,7 @@ async fn delete_custom_mod(branch: &str, mc_version: &str, mod_name: &str) -> Re
Ok(())
}

pub fn log(window: &Arc<std::sync::Mutex<Window>>, msg: &str) {
info!("{}", msg);

if let Ok(k) = window.lock() {
let _ = k.emit("process-output", msg);
}
}

fn handle_stdout(window: &Arc<std::sync::Mutex<Window>>, data: &[u8]) -> anyhow::Result<()> {
fn handle_stdout(window: &ShareableWindow, data: &[u8]) -> anyhow::Result<()> {
let data = String::from_utf8(data.to_vec())?;
if data.is_empty() {
return Ok(()); // ignore empty lines
Expand All @@ -223,7 +217,7 @@ fn handle_stdout(window: &Arc<std::sync::Mutex<Window>>, data: &[u8]) -> anyhow:
Ok(())
}

fn handle_stderr(window: &Arc<std::sync::Mutex<Window>>, data: &[u8]) -> anyhow::Result<()> {
fn handle_stderr(window: &ShareableWindow, data: &[u8]) -> anyhow::Result<()> {
let data = String::from_utf8(data.to_vec())?;
if data.is_empty() {
return Ok(()); // ignore empty lines
Expand All @@ -234,14 +228,29 @@ fn handle_stderr(window: &Arc<std::sync::Mutex<Window>>, data: &[u8]) -> anyhow:
Ok(())
}

fn handle_progress(window: &Arc<std::sync::Mutex<Window>>, progress_update: ProgressUpdate) -> anyhow::Result<()> {
window.lock().map_err(|_| anyhow!("Window lock is poisoned"))?.emit("progress-update", progress_update)?;
fn handle_progress(window: &ShareableWindow, progress_update: ProgressUpdate) -> anyhow::Result<()> {
window.lock().map_err(|_| anyhow!("Window lock is poisoned"))?.emit("progress-update", &progress_update)?;

// Check if progress update is label update
if let ProgressUpdate::SetLabel(label) = progress_update {
handle_log(window, &label)?;
}
Ok(())
}

fn handle_log(window: &ShareableWindow, msg: &str) -> anyhow::Result<()> {
info!("{}", msg);

if let Ok(k) = window.lock() {
let _ = k.emit("process-output", msg);
}
Ok(())
}

#[tauri::command]
async fn run_client(build_id: u32, account_data: MinecraftAccount, options: LauncherOptions, mods: Vec<LoaderMod>, window: Window, app_state: tauri::State<'_, AppState>) -> Result<(), String> {
let window_mutex = Arc::new(std::sync::Mutex::new(window));
// A shared mutex for the window object.
let shareable_window: ShareableWindow = Arc::new(Mutex::new(window));

let (account_name, uuid, token, user_type) = match account_data {
MinecraftAccount::MsaAccount { msa: _, xbl: _, mca, profile } => (profile.name, profile.id.to_string(), mca.data.access_token, "msa".to_string()),
Expand Down Expand Up @@ -292,31 +301,34 @@ async fn run_client(build_id: u32, account_data: MinecraftAccount, options: Laun
.block_on(async {
let keep_launcher_open = parameters.keep_launcher_open;

let launcher_data = LauncherData {
on_stdout: handle_stdout,
on_stderr: handle_stderr,
on_progress: handle_progress,
on_log: handle_log,
hide_window: |w| w.lock().unwrap().hide().unwrap(),
data: Box::new(shareable_window.clone()),
terminator: terminator_rx
};

if let Err(e) = prelauncher::launch(
launch_manifest,
parameters,
mods,
LauncherData {
on_stdout: handle_stdout,
on_stderr: handle_stderr,
on_progress: handle_progress,
data: Box::new(window_mutex.clone()),
terminator: terminator_rx
},
window_mutex.clone()
launcher_data
).await {
if !keep_launcher_open {
window_mutex.lock().unwrap().show().unwrap();
shareable_window.lock().unwrap().show().unwrap();
}

let message = format!("An error occourd:\n\n{:?}", e);
window_mutex.lock().unwrap().emit("client-error", format!("{}\n\n{}", message, ERROR_MSG)).unwrap();
handle_stderr(&window_mutex, message.as_bytes()).unwrap();
shareable_window.lock().unwrap().emit("client-error", format!("{}\n\n{}", message, ERROR_MSG)).unwrap();
handle_stderr(&shareable_window, message.as_bytes()).unwrap();
};

*copy_of_runner_instance.lock().map_err(|e| format!("unable to lock runner instance: {:?}", e)).unwrap()
= None;
window_mutex.lock().unwrap().emit("client-exited", ()).unwrap()
shareable_window.lock().unwrap().emit("client-exited", ()).unwrap()
});
});

Expand Down
15 changes: 7 additions & 8 deletions src-tauri/src/app/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ use anyhow::{anyhow, bail, Context, Result};
use tracing::{info, debug};
use tauri::{Manager, Url, WindowBuilder};
use tokio::time::sleep;
use crate::minecraft::progress::{ProgressReceiver, ProgressUpdate};
use crate::minecraft::{launcher::LauncherData, progress::{ProgressReceiver, ProgressUpdate}};

use super::gui::log;
use super::gui::ShareableWindow;

const MAX_DOWNLOAD_ATTEMPTS: u8 = 2;

pub async fn open_download_page(url: &str, on_progress: &impl ProgressReceiver, window: &Arc<Mutex<tauri::Window>>) -> Result<String> {
pub async fn open_download_page(url: &str, launcher_data: &LauncherData<ShareableWindow>) -> Result<String> {
let download_page: Url = format!("{}&liquidlauncher=1", url).parse()
.context("Failed to parse download page URL")?;

Expand All @@ -42,13 +42,12 @@ pub async fn open_download_page(url: &str, on_progress: &impl ProgressReceiver,
bail!("Failed to open download page after {} attempts", MAX_DOWNLOAD_ATTEMPTS);
}

log(&window, &format!("Opening download page... (Attempt {}/{})", count, MAX_DOWNLOAD_ATTEMPTS));
on_progress.progress_update(ProgressUpdate::SetLabel(format!("Opening download page... (Attempt {}/{})", count, MAX_DOWNLOAD_ATTEMPTS)));
launcher_data.progress_update(ProgressUpdate::SetLabel(format!("Opening download page... (Attempt {}/{})", count, MAX_DOWNLOAD_ATTEMPTS)));

match show_webview(download_page.clone(), window).await {
match show_webview(download_page.clone(), &launcher_data.data).await {
Ok(url) => break url,
Err(e) => {
log(&window, &format!("Failed to open download page: {:?}", e));
launcher_data.log(&format!("Failed to open download page: {:?}", e));
sleep(Duration::from_millis(500)).await;
}
}
Expand All @@ -59,7 +58,7 @@ pub async fn open_download_page(url: &str, on_progress: &impl ProgressReceiver,

async fn show_webview(url: Url, window: &Arc<Mutex<tauri::Window>>) -> Result<String> {
// Find download_view window from the window manager
let mut download_view = {
let download_view = {
let window = window.lock()
.map_err(|_| anyhow!("Failed to lock window"))?;

Expand Down
15 changes: 1 addition & 14 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
windows_subsystem = "windows"
)]

use std::{fs, io};
use std::io;
use once_cell::sync::Lazy;
use anyhow::Result;
use directories::ProjectDirs;
Expand Down Expand Up @@ -64,19 +64,6 @@ static HTTP_CLIENT: Lazy<Client> = Lazy::new(|| {
client
});

/// Creates a directory tree if it doesn't exist
macro_rules! mkdir {
($path:expr) => {
// Check if directory exists
if !$path.exists() {
// Create directory
if let Err(e) = fs::create_dir_all($path) {
error!("Failed to create directory {:?}: {}", $path, e);
}
}
};
}

pub fn main() -> Result<()> {
use tracing_subscriber::{fmt, EnvFilter};

Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/minecraft/java/distribution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl Default for JavaDistribution {
}

impl JavaDistribution {
pub fn get_url(&self, jre_version: &str, os_name: &str, os_arch: &str) -> String {
pub fn get_url(&self, jre_version: &u32, os_name: &str, os_arch: &str) -> String {
match self {
JavaDistribution::Temurin => {
format!(
Expand Down
41 changes: 30 additions & 11 deletions src-tauri/src/minecraft/java/jre_downloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,26 @@
* You should have received a copy of the GNU General Public License
* along with LiquidLauncher. If not, see <https://www.gnu.org/licenses/>.
*/

use std::io::Cursor;
use std::path::{Path, PathBuf};

use anyhow::{bail, Result};
use path_absolutize::Absolutize;
use tokio::fs;

use crate::utils::{download_file, tar_gz_extract, zip_extract, ARCHITECTURE, OperatingSystem, OS};
use crate::utils::{download_file, tar_gz_extract, zip_extract, OperatingSystem, ARCHITECTURE, OS};

use super::JavaDistribution;

/// Find java binary in JRE folder
pub async fn find_java_binary(runtimes_folder: &Path, jre_distribution: &JavaDistribution, jre_version: &str) -> Result<PathBuf> {
let runtime_path = runtimes_folder.join(format!("{}_{}", jre_distribution.get_name(), jre_version));
pub async fn find_java_binary(
runtimes_folder: &Path,
jre_distribution: &JavaDistribution,
jre_version: &u32,
) -> Result<PathBuf> {
let runtime_path =
runtimes_folder.join(format!("{}_{}", jre_distribution.get_name(), jre_version));

// Find JRE in runtime folder
let mut files = fs::read_dir(&runtime_path).await?;
Expand All @@ -40,8 +45,12 @@ pub async fn find_java_binary(runtimes_folder: &Path, jre_distribution: &JavaDis

let java_binary = match OS {
OperatingSystem::WINDOWS => folder_path.join("bin").join("javaw.exe"),
OperatingSystem::OSX => folder_path.join("Contents").join("Home").join("bin").join("java"),
_ => folder_path.join("bin").join("java")
OperatingSystem::OSX => folder_path
.join("Contents")
.join("Home")
.join("bin")
.join("java"),
_ => folder_path.join("bin").join("java"),
};

if java_binary.exists() {
Expand All @@ -68,8 +77,17 @@ pub async fn find_java_binary(runtimes_folder: &Path, jre_distribution: &JavaDis
}

/// Download specific JRE to runtimes
pub async fn jre_download<F>(runtimes_folder: &Path, jre_distribution: &JavaDistribution, jre_version: &str, on_progress: F) -> Result<PathBuf> where F : Fn(u64, u64) {
let runtime_path = runtimes_folder.join(format!("{}_{}", jre_distribution.get_name(), jre_version));
pub async fn jre_download<F>(
runtimes_folder: &Path,
jre_distribution: &JavaDistribution,
jre_version: &u32,
on_progress: F,
) -> Result<PathBuf>
where
F: Fn(u64, u64),
{
let runtime_path =
runtimes_folder.join(format!("{}_{}", jre_distribution.get_name(), jre_version));

if runtime_path.exists() {
// Clear out folder
Expand All @@ -91,11 +109,12 @@ pub async fn jre_download<F>(runtimes_folder: &Path, jre_distribution: &JavaDist

match OS {
OperatingSystem::WINDOWS => zip_extract(cursor, runtime_path.as_path()).await?,
OperatingSystem::LINUX | OperatingSystem::OSX => tar_gz_extract(cursor, runtime_path.as_path()).await?,
_ => bail!("Unsupported OS")
OperatingSystem::LINUX | OperatingSystem::OSX => {
tar_gz_extract(cursor, runtime_path.as_path()).await?
}
_ => bail!("Unsupported OS"),
}

// Find JRE afterwards
find_java_binary(runtimes_folder, jre_distribution, jre_version).await
}

2 changes: 2 additions & 0 deletions src-tauri/src/minecraft/java/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ impl JavaRuntime {
if !self.0.exists() {
bail!("Java runtime not found at: {}", self.0.display());
}

debug!("Executing Java runtime: {}", self.0.display());

let mut command = Command::new(&self.0);
command.current_dir(game_dir);
Expand Down
Loading

0 comments on commit affa1c7

Please sign in to comment.