Compare commits
20 Commits
df3bd69141
...
3.0.1
Author | SHA1 | Date | |
---|---|---|---|
f214aa454e | |||
9d2599dd2f | |||
eddaaaaa2f | |||
a21abe86bb | |||
d685114bd7 | |||
4e4998671a | |||
5cae8bc63a | |||
409c8b0b04 | |||
c395662134 | |||
89d1bcbd86 | |||
c3c13b0e07 | |||
4e1f76a713 | |||
4fb2ab7bed | |||
bb90e28d92 | |||
a554c53f89 | |||
307e0c9747 | |||
86033e2d6a | |||
1a563e64d5 | |||
5aec2d8245 | |||
87742b66b7 |
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -7,6 +7,7 @@
|
|||||||
"fill-labs.dependi",
|
"fill-labs.dependi",
|
||||||
"mylesmurphy.prettify-ts",
|
"mylesmurphy.prettify-ts",
|
||||||
"edwinhuish.better-comments-next",
|
"edwinhuish.better-comments-next",
|
||||||
"dbaeumer.vscode-eslint"
|
"dbaeumer.vscode-eslint",
|
||||||
|
"bradlc.vscode-tailwindcss"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,8 @@ It enhances the osu! experience with quality-of-life features and integration sp
|
|||||||
- [x] Shows the number of imported beatmapsets
|
- [x] Shows the number of imported beatmapsets
|
||||||
- [x] Shows the number of imported skins
|
- [x] Shows the number of imported skins
|
||||||
- [x] Displays ping to the EZPPFarm server
|
- [x] Displays ping to the EZPPFarm server
|
||||||
- [ ] Discord Rich Presence (planned and in development)
|
- [x] Discord Rich Presence
|
||||||
- [ ] Performance Display Overlay (planned)
|
- [x] Performance Display Overlay (currently in experimental patcher release stream)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -31,9 +31,9 @@ It enhances the osu! experience with quality-of-life features and integration sp
|
|||||||
| -------- | ---------------- |
|
| -------- | ---------------- |
|
||||||
| Windows | ✅ Supported |
|
| Windows | ✅ Supported |
|
||||||
| macOS | ❌ Not supported |
|
| macOS | ❌ Not supported |
|
||||||
| Linux | ❌ Not supported |
|
| Linux | 🕧 Partially supported (via osu-winello) |
|
||||||
|
|
||||||
> Currently, only **Windows** is supported. Support for other platforms may be considered in the future.
|
> Currently, only **Windows** is fully supported. Support for other platforms may be considered in the future.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
4
bun.lock
4
bun.lock
@@ -7,7 +7,7 @@
|
|||||||
"@better-fetch/fetch": "^1.1.18",
|
"@better-fetch/fetch": "^1.1.18",
|
||||||
"@fontsource/sora": "^5.2.6",
|
"@fontsource/sora": "^5.2.6",
|
||||||
"@fontsource/space-mono": "^5.2.8",
|
"@fontsource/space-mono": "^5.2.8",
|
||||||
"@iarna/toml": "^3.0.0",
|
"@iarna/toml": "2.2.5",
|
||||||
"@number-flow/svelte": "^0.3.9",
|
"@number-flow/svelte": "^0.3.9",
|
||||||
"@tailwindcss/typography": "0.5.16",
|
"@tailwindcss/typography": "0.5.16",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.11",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
|
|
||||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||||
|
|
||||||
"@iarna/toml": ["@iarna/toml@3.0.0", "", {}, "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q=="],
|
"@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="],
|
||||||
|
|
||||||
"@internationalized/date": ["@internationalized/date@3.8.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA=="],
|
"@internationalized/date": ["@internationalized/date@3.8.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA=="],
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
"@better-fetch/fetch": "^1.1.18",
|
"@better-fetch/fetch": "^1.1.18",
|
||||||
"@fontsource/sora": "^5.2.6",
|
"@fontsource/sora": "^5.2.6",
|
||||||
"@fontsource/space-mono": "^5.2.8",
|
"@fontsource/space-mono": "^5.2.8",
|
||||||
"@iarna/toml": "^3.0.0",
|
"@iarna/toml": "2.2.5",
|
||||||
"@number-flow/svelte": "^0.3.9",
|
"@number-flow/svelte": "^0.3.9",
|
||||||
"@tailwindcss/typography": "0.5.16",
|
"@tailwindcss/typography": "0.5.16",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.11",
|
||||||
|
10
src-tauri/Cargo.lock
generated
10
src-tauri/Cargo.lock
generated
@@ -1094,8 +1094,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ezpplauncher"
|
name = "ezpplauncher"
|
||||||
version = "3.0.0-beta.3"
|
version = "3.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.21.7",
|
||||||
"discord-rich-presence",
|
"discord-rich-presence",
|
||||||
"hardware-id",
|
"hardware-id",
|
||||||
"md5",
|
"md5",
|
||||||
@@ -1115,6 +1116,7 @@ dependencies = [
|
|||||||
"tauri-plugin-single-instance",
|
"tauri-plugin-single-instance",
|
||||||
"tauri-plugin-sql",
|
"tauri-plugin-sql",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"widestring",
|
||||||
"winapi",
|
"winapi",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
"winreg 0.55.0",
|
"winreg 0.55.0",
|
||||||
@@ -5798,6 +5800,12 @@ dependencies = [
|
|||||||
"wasite",
|
"wasite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "widestring"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ezpplauncher"
|
name = "ezpplauncher"
|
||||||
version = "3.0.0-beta.3"
|
version = "3.0.1"
|
||||||
description = "EZPPLauncher redefined."
|
description = "EZPPLauncher redefined."
|
||||||
authors = ["HorizonCode"]
|
authors = ["HorizonCode"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
@@ -39,7 +39,9 @@ once_cell = "1.21.3"
|
|||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winreg = "0.55.0"
|
winreg = "0.55.0"
|
||||||
winapi = { version = "0.3", features = ["winuser"] }
|
winapi = { version = "0.3", features = ["winuser", "wincrypt", "memoryapi", "winbase", "dpapi"] }
|
||||||
|
base64 = "0.21"
|
||||||
|
widestring = "1.0"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-single-instance = "2.3.0"
|
tauri-plugin-single-instance = "2.3.0"
|
||||||
|
@@ -13,7 +13,8 @@ use tokio::time::{Duration, sleep};
|
|||||||
|
|
||||||
use crate::presence;
|
use crate::presence;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
check_folder_completeness, get_osu_config, get_osu_user_config, get_window_title_by_pid,
|
check_folder_completeness, encrypt_password, get_osu_config, get_osu_user_config,
|
||||||
|
get_window_title_by_pid, is_net8_installed, is_osuwinello_available, is_wmctrl_available,
|
||||||
set_osu_config_vals, set_osu_user_config_vals,
|
set_osu_config_vals, set_osu_user_config_vals,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -282,8 +283,6 @@ pub fn set_osu_config_values(
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
||||||
let osu_exe_path = PathBuf::from(&folder).join("osu!.exe");
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -292,6 +291,7 @@ pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
|||||||
let mut updater_process = {
|
let mut updater_process = {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
|
let osu_exe_path = PathBuf::from(&folder).join("osu!.exe");
|
||||||
Command::new(&osu_exe_path)
|
Command::new(&osu_exe_path)
|
||||||
.arg("-repair")
|
.arg("-repair")
|
||||||
.creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
|
.creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
|
||||||
@@ -301,7 +301,7 @@ pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
|||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
Command::new(&osu_exe_path)
|
Command::new("osu-wine")
|
||||||
.arg("-repair")
|
.arg("-repair")
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| format!("Failed to spawn updater: {}", e))?
|
.map_err(|e| format!("Failed to spawn updater: {}", e))?
|
||||||
@@ -337,10 +337,8 @@ pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
|||||||
sleep(Duration::from_millis(500)).await;
|
sleep(Duration::from_millis(500)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for updater process to fully exit
|
|
||||||
let _ = updater_process.wait().await;
|
let _ = updater_process.wait().await;
|
||||||
|
|
||||||
// Clean up update-related files
|
|
||||||
let force_update_files = [".require_update", "help.txt", "_pending"];
|
let force_update_files = [".require_update", "help.txt", "_pending"];
|
||||||
for update_file_name in &force_update_files {
|
for update_file_name in &force_update_files {
|
||||||
let path = PathBuf::from(&folder).join(update_file_name);
|
let path = PathBuf::from(&folder).join(update_file_name);
|
||||||
@@ -372,8 +370,6 @@ pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
|||||||
/* #[cfg(windows)]
|
/* #[cfg(windows)]
|
||||||
use std::os::windows::process::CommandExt; */
|
use std::os::windows::process::CommandExt; */
|
||||||
|
|
||||||
let osu_exe_path = PathBuf::from(&folder).join("osu!.exe");
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -382,6 +378,7 @@ pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
|||||||
let mut game_process = {
|
let mut game_process = {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
|
let osu_exe_path = PathBuf::from(&folder).join("osu!.exe");
|
||||||
Command::new(&osu_exe_path)
|
Command::new(&osu_exe_path)
|
||||||
.arg("-devserver")
|
.arg("-devserver")
|
||||||
.arg("ez-pp.farm")
|
.arg("ez-pp.farm")
|
||||||
@@ -392,8 +389,8 @@ pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
|||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
Command::new(&osu_exe_path)
|
Command::new("osu-wine")
|
||||||
.arg("-devserver")
|
.arg("--devserver")
|
||||||
.arg("ez-pp.farm")
|
.arg("ez-pp.farm")
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| format!("Failed to spawn updater: {}", e))?
|
.map_err(|e| format!("Failed to spawn updater: {}", e))?
|
||||||
@@ -416,13 +413,6 @@ pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
|||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| format!("Failed to run patcher: {e}"))?;
|
.map_err(|e| format!("Failed to run patcher: {e}"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
{
|
|
||||||
let _ = Command::new(&patcher_exe_path)
|
|
||||||
.spawn()
|
|
||||||
.map_err(|e| format!("Failed to run patcher: {e}"))?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,6 +434,7 @@ pub struct UpdateFile {
|
|||||||
pub async fn get_ezpp_launcher_update_files(
|
pub async fn get_ezpp_launcher_update_files(
|
||||||
folder: String,
|
folder: String,
|
||||||
update_url: String,
|
update_url: String,
|
||||||
|
update_stream: String,
|
||||||
) -> Result<(Vec<UpdateFile>, Vec<UpdateFile>), String> {
|
) -> Result<(Vec<UpdateFile>, Vec<UpdateFile>), String> {
|
||||||
let osu_path = PathBuf::from(folder);
|
let osu_path = PathBuf::from(folder);
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
@@ -451,6 +442,7 @@ pub async fn get_ezpp_launcher_update_files(
|
|||||||
let update_files = client
|
let update_files = client
|
||||||
.patch(update_url)
|
.patch(update_url)
|
||||||
.header("User-Agent", "EZPPLauncher")
|
.header("User-Agent", "EZPPLauncher")
|
||||||
|
.query(&[("stream", update_stream)])
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?
|
.map_err(|e| e.to_string())?
|
||||||
@@ -543,7 +535,6 @@ pub async fn download_ezpp_launcher_update_files(
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
// Emit progress to frontend
|
|
||||||
app.emit(
|
app.emit(
|
||||||
"download-progress",
|
"download-progress",
|
||||||
UpdateStatus {
|
UpdateStatus {
|
||||||
@@ -713,3 +704,36 @@ pub async fn presence_update_user(user: PresenceUser) {
|
|||||||
pub async fn presence_is_connected() -> bool {
|
pub async fn presence_is_connected() -> bool {
|
||||||
presence::has_presence().await
|
presence::has_presence().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn has_wmctrl() -> bool {
|
||||||
|
is_wmctrl_available()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn has_osuwinello() -> bool {
|
||||||
|
is_osuwinello_available()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn has_net8() -> bool {
|
||||||
|
is_net8_installed().await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn encrypt_string(string: String, entropy: String) -> String {
|
||||||
|
let encrypted = encrypt_password(&string, &entropy);
|
||||||
|
|
||||||
|
match encrypted {
|
||||||
|
Ok(encrypted_vec) => encrypted_vec,
|
||||||
|
Err(_) => string,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: should not be called by tauri on non windows systems, return the string nonthenless
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn encrypt_string(string: String, _entropy: String) -> String {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
@@ -5,17 +5,17 @@ pub mod commands;
|
|||||||
pub mod presence;
|
pub mod presence;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
check_for_corruption, download_ezpp_launcher_update_files, exit, find_osu_installation,
|
check_for_corruption, download_ezpp_launcher_update_files, encrypt_string, exit,
|
||||||
get_beatmapsets_count, get_ezpp_launcher_update_files, get_hwid, get_launcher_version,
|
find_osu_installation, get_beatmapsets_count, get_ezpp_launcher_update_files, get_hwid,
|
||||||
get_osu_release_stream, get_osu_skin, get_osu_version, get_platform, get_skins_count,
|
get_launcher_version, get_osu_release_stream, get_osu_skin, get_osu_version, get_platform,
|
||||||
is_osu_running, open_url_in_browser, presence_connect, presence_disconnect,
|
get_skins_count, has_net8, has_osuwinello, has_wmctrl, is_osu_running, open_url_in_browser,
|
||||||
presence_is_connected, presence_update_status, presence_update_user, replace_ui_files, run_osu,
|
presence_connect, presence_disconnect, presence_is_connected, presence_update_status,
|
||||||
run_osu_updater, set_osu_config_values, set_osu_user_config_values, valid_osu_folder,
|
presence_update_user, replace_ui_files, run_osu, run_osu_updater, set_osu_config_values,
|
||||||
|
set_osu_user_config_values, valid_osu_folder,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
unsafe {
|
unsafe {
|
||||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||||
@@ -26,9 +26,6 @@ pub fn run() {
|
|||||||
{
|
{
|
||||||
builder = builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
builder = builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||||
let app_window = app.get_webview_window("main").expect("no main window");
|
let app_window = app.get_webview_window("main").expect("no main window");
|
||||||
app_window
|
|
||||||
.set_always_on_top(true)
|
|
||||||
.expect("failed to set always on top");
|
|
||||||
app_window.set_focus().expect("failed to focus");
|
app_window.set_focus().expect("failed to focus");
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -60,7 +57,11 @@ pub fn run() {
|
|||||||
presence_disconnect,
|
presence_disconnect,
|
||||||
presence_update_status,
|
presence_update_status,
|
||||||
presence_update_user,
|
presence_update_user,
|
||||||
presence_is_connected
|
presence_is_connected,
|
||||||
|
has_osuwinello,
|
||||||
|
has_wmctrl,
|
||||||
|
has_net8,
|
||||||
|
encrypt_string
|
||||||
])
|
])
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
@@ -71,7 +71,6 @@ pub fn set_osu_user_config_vals(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect indices and keys to update to avoid borrow checker issues
|
|
||||||
let mut updates = Vec::new();
|
let mut updates = Vec::new();
|
||||||
for (i, line) in lines.iter().enumerate() {
|
for (i, line) in lines.iter().enumerate() {
|
||||||
if let Some((existing_key, _)) = line.split_once(" = ") {
|
if let Some((existing_key, _)) = line.split_once(" = ") {
|
||||||
@@ -86,7 +85,6 @@ pub fn set_osu_user_config_vals(
|
|||||||
keys_to_add.remove(trimmed_key.as_str());
|
keys_to_add.remove(trimmed_key.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new keys that were not found
|
|
||||||
for key in keys_to_add {
|
for key in keys_to_add {
|
||||||
if let Some(value) = keys_to_set.get(key) {
|
if let Some(value) = keys_to_set.get(key) {
|
||||||
lines.push(format!("{} = {}", key, value));
|
lines.push(format!("{} = {}", key, value));
|
||||||
@@ -139,7 +137,6 @@ pub fn set_osu_config_vals(
|
|||||||
keys_to_add.remove(trimmed_key.as_str());
|
keys_to_add.remove(trimmed_key.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new keys that were not found
|
|
||||||
for key in keys_to_add {
|
for key in keys_to_add {
|
||||||
if let Some(value) = keys_to_set.get(key) {
|
if let Some(value) = keys_to_set.get(key) {
|
||||||
lines.push(format!("{} = {}", key, value));
|
lines.push(format!("{} = {}", key, value));
|
||||||
@@ -177,19 +174,78 @@ pub fn get_osu_config<P: AsRef<Path>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
pub fn get_window_title_by_pid(_pid: Pid) -> String {
|
pub fn is_osuwinello_available() -> bool {
|
||||||
"".to_string()
|
use std::process::Command;
|
||||||
|
Command::new("osu-wine")
|
||||||
|
.arg("--info")
|
||||||
|
.stdout(std::process::Stdio::null())
|
||||||
|
.stderr(std::process::Stdio::null())
|
||||||
|
.status()
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn is_osuwinello_available() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub fn is_wmctrl_available() -> bool {
|
||||||
|
use std::process::Command;
|
||||||
|
Command::new("wmctrl")
|
||||||
|
.arg("-V")
|
||||||
|
.stdout(std::process::Stdio::null())
|
||||||
|
.stderr(std::process::Stdio::null())
|
||||||
|
.status()
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn is_wmctrl_available() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub fn get_window_title_by_pid(target_pid: Pid) -> String {
|
||||||
|
use std::process::Command;
|
||||||
|
let find_title = || -> Option<String> {
|
||||||
|
let output = Command::new("wmctrl").arg("-lp").output().ok()?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output_str = String::from_utf8(output.stdout).ok()?;
|
||||||
|
|
||||||
|
for line in output_str.lines() {
|
||||||
|
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||||
|
if parts.len() < 4 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(pid) = parts[2].parse::<u32>() {
|
||||||
|
if pid == target_pid.as_u32() {
|
||||||
|
let title = parts[4..].join(" ");
|
||||||
|
return Some(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
find_title().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn get_window_title_by_pid(pid: Pid) -> String {
|
pub fn get_window_title_by_pid(pid: Pid) -> String {
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::os::windows::ffi::OsStringExt;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use winapi::shared::windef::HWND;
|
use winapi::shared::windef::HWND;
|
||||||
use winapi::um::winuser::{
|
use winapi::um::winuser::{
|
||||||
EnumWindows, GetWindowTextW, GetWindowThreadProcessId, IsWindowVisible,
|
EnumWindows, GetWindowTextW, GetWindowThreadProcessId, IsWindowVisible,
|
||||||
};
|
};
|
||||||
use std::ffi::OsString;
|
|
||||||
use std::os::windows::ffi::OsStringExt;
|
|
||||||
|
|
||||||
extern "system" fn enum_windows_proc(
|
extern "system" fn enum_windows_proc(
|
||||||
hwnd: HWND,
|
hwnd: HWND,
|
||||||
@@ -210,11 +266,11 @@ pub fn get_window_title_by_pid(pid: Pid) -> String {
|
|||||||
let title_str = title.to_string_lossy().into_owned();
|
let title_str = title.to_string_lossy().into_owned();
|
||||||
if !title_str.is_empty() {
|
if !title_str.is_empty() {
|
||||||
*result.lock().unwrap() = Some(title_str);
|
*result.lock().unwrap() = Some(title_str);
|
||||||
return 0; // Stop enumeration
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 // Continue enumeration
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,3 +284,92 @@ pub fn get_window_title_by_pid(pid: Pid) -> String {
|
|||||||
}
|
}
|
||||||
result.lock().unwrap().clone().unwrap_or_default()
|
result.lock().unwrap().clone().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn is_net8_installed() -> bool {
|
||||||
|
use std::process::Command;
|
||||||
|
let output_result = Command::new("dotnet").arg("--list-runtimes").output();
|
||||||
|
match output_result {
|
||||||
|
Ok(output) => {
|
||||||
|
if !output.status.success() {
|
||||||
|
eprintln!(
|
||||||
|
"Error: `dotnet --list-runtimes` failed with status: {}",
|
||||||
|
output.status
|
||||||
|
);
|
||||||
|
eprintln!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stdout_str = String::from_utf8_lossy(&output.stdout);
|
||||||
|
stdout_str
|
||||||
|
.lines()
|
||||||
|
.any(|line| line.starts_with("Microsoft.WindowsDesktop.App 8."))
|
||||||
|
}
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn encrypt_password(password: &str, entropy: &str) -> Result<String, String> {
|
||||||
|
use base64::{Engine as _, engine::general_purpose};
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::os::windows::ffi::OsStrExt;
|
||||||
|
use std::ptr;
|
||||||
|
use std::slice;
|
||||||
|
use winapi::shared::minwindef::{BYTE, DWORD, LPVOID};
|
||||||
|
use winapi::shared::ntdef::LPCWSTR;
|
||||||
|
use winapi::um::dpapi::{CRYPTPROTECT_UI_FORBIDDEN, CryptProtectData};
|
||||||
|
use winapi::um::winbase::LocalFree;
|
||||||
|
use winapi::um::wincrypt::DATA_BLOB;
|
||||||
|
|
||||||
|
let description = "Encrypted";
|
||||||
|
|
||||||
|
let password_bytes = password.as_bytes();
|
||||||
|
let mut input_blob = DATA_BLOB {
|
||||||
|
cbData: password_bytes.len() as DWORD,
|
||||||
|
pbData: password_bytes.as_ptr() as *mut BYTE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let entropy_bytes = entropy.as_bytes();
|
||||||
|
let mut entropy_blob = DATA_BLOB {
|
||||||
|
cbData: entropy_bytes.len() as DWORD,
|
||||||
|
pbData: entropy_bytes.as_ptr() as *mut BYTE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut output_blob = DATA_BLOB {
|
||||||
|
cbData: 0,
|
||||||
|
pbData: ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let wide_description: Vec<u16> = OsStrExt::encode_wide(OsStr::new(description))
|
||||||
|
.chain(Some(0))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let p_description: LPCWSTR = wide_description.as_ptr();
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
CryptProtectData(
|
||||||
|
&mut input_blob,
|
||||||
|
p_description,
|
||||||
|
&mut entropy_blob,
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
CRYPTPROTECT_UI_FORBIDDEN,
|
||||||
|
&mut output_blob,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if result == 0 {
|
||||||
|
return Err("CryptProtectData failed".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let encrypted_data =
|
||||||
|
unsafe { slice::from_raw_parts(output_blob.pbData, output_blob.cbData as usize).to_vec() };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
LocalFree(output_blob.pbData as LPVOID);
|
||||||
|
}
|
||||||
|
|
||||||
|
let base64_string = general_purpose::STANDARD_NO_PAD.encode(&encrypted_data);
|
||||||
|
|
||||||
|
Ok(base64_string)
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "ezpplauncher",
|
"productName": "ezpplauncher",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.1",
|
||||||
"identifier": "farm.ezpp.launcher",
|
"identifier": "farm.ezpp.launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "bun run vite:dev",
|
"beforeDevCommand": "bun run vite:dev",
|
||||||
|
@@ -6,9 +6,14 @@ import type { Release } from './types';
|
|||||||
|
|
||||||
export const currentView = writable<Component>(Loading);
|
export const currentView = writable<Component>(Loading);
|
||||||
|
|
||||||
|
export const platform = writable<string>("");
|
||||||
|
|
||||||
export const launcherVersion = writable<string>('');
|
export const launcherVersion = writable<string>('');
|
||||||
export const newVersion = writable<Release | undefined>(undefined);
|
export const newVersion = writable<Release | undefined>(undefined);
|
||||||
|
|
||||||
|
export const launcherStreams = writable<string[]>(['stable']);
|
||||||
|
export const launcherStream = writable<string>('stable');
|
||||||
|
|
||||||
export const discordPresence = writable<boolean>(false);
|
export const discordPresence = writable<boolean>(false);
|
||||||
export const presenceLoading = writable<boolean>(false);
|
export const presenceLoading = writable<boolean>(false);
|
||||||
|
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import type { UpdateFile, UpdateStatus } from './types';
|
import type { UpdateFile, UpdateStatus } from './types';
|
||||||
import { listen } from '@tauri-apps/api/event';
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
import { betterFetch } from '@better-fetch/fetch';
|
||||||
|
|
||||||
const updateUrl = 'https://ez-pp.farm/ezpplauncher';
|
const updateUrl = 'https://next.ez-pp.farm/api/ezpplauncher';
|
||||||
|
|
||||||
export const getHWID = async () => {
|
export const getHWID = async () => {
|
||||||
const hwid = await invoke('get_hwid');
|
const hwid = await invoke('get_hwid');
|
||||||
@@ -73,8 +74,24 @@ export const runUpdater = async (folder: string) => await invoke('run_osu_update
|
|||||||
export const runOsu = async (folder: string, patch: boolean) =>
|
export const runOsu = async (folder: string, patch: boolean) =>
|
||||||
await invoke('run_osu', { folder, patch });
|
await invoke('run_osu', { folder, patch });
|
||||||
|
|
||||||
export const getEZPPLauncherUpdateFiles = async (folder: string) => {
|
export const getEZPPLauncherStreams = async () => {
|
||||||
const result = await invoke('get_ezpp_launcher_update_files', { folder, updateUrl });
|
const resp = await betterFetch<{ streams: string[] }>(updateUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!resp.error) {
|
||||||
|
return resp.data.streams;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getEZPPLauncherUpdateFiles = async (folder: string, updateStream: string) => {
|
||||||
|
const result = await invoke('get_ezpp_launcher_update_files', {
|
||||||
|
folder,
|
||||||
|
updateUrl,
|
||||||
|
updateStream,
|
||||||
|
});
|
||||||
if (typeof result === 'object') {
|
if (typeof result === 'object') {
|
||||||
const [filesToDownload, updateFiles] = result as [UpdateFile[], UpdateFile[]];
|
const [filesToDownload, updateFiles] = result as [UpdateFile[], UpdateFile[]];
|
||||||
return {
|
return {
|
||||||
@@ -116,3 +133,11 @@ export const exit = async () => await invoke('exit');
|
|||||||
export const getPlatform = async () => await invoke<string>('get_platform');
|
export const getPlatform = async () => await invoke<string>('get_platform');
|
||||||
export const isOsuCorrupted = async (folder: string) =>
|
export const isOsuCorrupted = async (folder: string) =>
|
||||||
await invoke<boolean>('check_for_corruption', { folder });
|
await invoke<boolean>('check_for_corruption', { folder });
|
||||||
|
export const hasWMCTRL = async () =>
|
||||||
|
await invoke<boolean>('has_wmctrl');
|
||||||
|
export const hasOsuWinello = async () =>
|
||||||
|
await invoke<boolean>('has_osuwinello');
|
||||||
|
export const hasNet8 = async () =>
|
||||||
|
await invoke<boolean>('has_net8');
|
||||||
|
export const encryptString = async (str: string, entropy: string) =>
|
||||||
|
await invoke<string>('encrypt_string', {string: str, entropy});
|
@@ -9,11 +9,14 @@
|
|||||||
currentSkin,
|
currentSkin,
|
||||||
currentView,
|
currentView,
|
||||||
discordPresence,
|
discordPresence,
|
||||||
|
launcherStream,
|
||||||
|
launcherStreams,
|
||||||
launcherVersion,
|
launcherVersion,
|
||||||
launching,
|
launching,
|
||||||
newVersion,
|
newVersion,
|
||||||
osuBuild,
|
osuBuild,
|
||||||
osuStream,
|
osuStream,
|
||||||
|
platform,
|
||||||
presenceLoading,
|
presenceLoading,
|
||||||
serverConnectionFails,
|
serverConnectionFails,
|
||||||
serverPing,
|
serverPing,
|
||||||
@@ -80,6 +83,7 @@
|
|||||||
import { osuapi } from '@/api/osuapi';
|
import { osuapi } from '@/api/osuapi';
|
||||||
import {
|
import {
|
||||||
downloadEZPPLauncherUpdateFiles,
|
downloadEZPPLauncherUpdateFiles,
|
||||||
|
encryptString,
|
||||||
exit,
|
exit,
|
||||||
getBeatmapSetsCount,
|
getBeatmapSetsCount,
|
||||||
getEZPPLauncherUpdateFiles,
|
getEZPPLauncherUpdateFiles,
|
||||||
@@ -87,6 +91,9 @@
|
|||||||
getSkin,
|
getSkin,
|
||||||
getSkinsCount,
|
getSkinsCount,
|
||||||
getVersion,
|
getVersion,
|
||||||
|
hasNet8,
|
||||||
|
hasOsuWinello,
|
||||||
|
hasWMCTRL,
|
||||||
isOsuCorrupted,
|
isOsuCorrupted,
|
||||||
isOsuRunning,
|
isOsuRunning,
|
||||||
isValidOsuFolder,
|
isValidOsuFolder,
|
||||||
@@ -184,9 +191,26 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($platform === 'linux') {
|
||||||
|
if (!(await hasWMCTRL())) {
|
||||||
|
toast.error('Hmmm...', {
|
||||||
|
description: 'wmctrl seems to be missing, please install via AUR.',
|
||||||
|
});
|
||||||
|
launching.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(await hasOsuWinello())) {
|
||||||
|
toast.error('Hmmm...', {
|
||||||
|
description: 'osu-winello seems to be missing, please install it.',
|
||||||
|
});
|
||||||
|
launching.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
launchInfo = 'Looking for EZPPLauncher File updates...';
|
launchInfo = 'Looking for EZPPLauncher File updates...';
|
||||||
const updateResult = await getEZPPLauncherUpdateFiles(osuPath);
|
const updateResult = await getEZPPLauncherUpdateFiles(osuPath, $launcherStream);
|
||||||
|
|
||||||
if (updateResult) {
|
if (updateResult) {
|
||||||
if (updateResult.filesToDownload.length > 0) {
|
if (updateResult.filesToDownload.length > 0) {
|
||||||
@@ -273,7 +297,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Password',
|
key: 'Password',
|
||||||
value: password,
|
value: $platform === "windows" ? await encryptString(password, "cu24180ncjeiu0ci1nwui") : password,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'SaveUsername',
|
key: 'SaveUsername',
|
||||||
@@ -802,7 +826,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-6 w-full h-full bg-theme-900/40 p-6">
|
<div class="flex flex-col gap-6 w-full h-full bg-theme-900/40 p-6">
|
||||||
<div
|
<div
|
||||||
class="flex flex-row flex-nowrap h-11 w-full bg-theme-800/50 border border-theme-800/90 rounded-lg p-[4px]"
|
class="flex flex-row flex-nowrap h-11 gap-1 w-full bg-theme-800/50 border border-theme-800/90 rounded-lg p-[4px]"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="w-full flex justify-center items-center font-semibold text-sm rounded-lg {selectedTab ===
|
class="w-full flex justify-center items-center font-semibold text-sm rounded-lg {selectedTab ===
|
||||||
@@ -1028,11 +1052,18 @@
|
|||||||
>
|
>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<Label class="text-sm" for="setting-custom-cursor">Patching</Label>
|
<Label class="text-sm" for="setting-custom-cursor">Patching</Label>
|
||||||
<div class="text-muted-foreground text-xs">Shows misses in Relax and Autopilot</div>
|
<div class="text-muted-foreground text-xs">
|
||||||
|
Shows misses in Relax and Autopilot {#if $platform !== 'windows'}<span
|
||||||
|
class="text-red-500 bg-red-800/20 border border-red-600/20 p-0.5 mx-1 px-2 rounded-lg"
|
||||||
|
>currently only on windows!</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="setting-custom-cursor"
|
id="setting-custom-cursor"
|
||||||
checked={$patch}
|
checked={$platform === 'windows' ? $patch : false}
|
||||||
|
disabled={$platform !== 'windows'}
|
||||||
onCheckedChange={async (e) => {
|
onCheckedChange={async (e) => {
|
||||||
patch.set(e);
|
patch.set(e);
|
||||||
$userSettings.save();
|
$userSettings.save();
|
||||||
@@ -1115,7 +1146,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-[0.7fr_auto] gap-y-5 items-center border-theme-800 pl-6 pr-5 pb-4"
|
class="grid grid-cols-[0.7fr_auto] gap-y-1 items-center border-theme-800 pl-6 pr-5 pb-4"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<Label class="text-sm" for="setting-custom-cursor">osu! installation path</Label>
|
<Label class="text-sm" for="setting-custom-cursor">osu! installation path</Label>
|
||||||
@@ -1135,6 +1166,54 @@
|
|||||||
onclick={browse_osu_installation}>Browse</Button
|
onclick={browse_osu_installation}>Browse</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<Label class="text-sm" for="setting-custom-cursor">patcher release stream</Label>
|
||||||
|
<div class="text-muted-foreground text-xs">
|
||||||
|
test different versions of the patcher
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row w-full">
|
||||||
|
<Select.Root
|
||||||
|
type="single"
|
||||||
|
bind:value={$launcherStream}
|
||||||
|
onValueChange={async (newStream) => {
|
||||||
|
if (newStream === 'experimental' && !(await hasNet8())) {
|
||||||
|
launcherStream.set('stable');
|
||||||
|
toast.error('.NET 8.0 Desktop Runtime not found!', {
|
||||||
|
action: {
|
||||||
|
label: 'Download .NET 8.0',
|
||||||
|
onClick: async () =>
|
||||||
|
await openURL(
|
||||||
|
'https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-8.0.18-windows-x64-installer'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$userSettings.value('patcherStream').set(newStream);
|
||||||
|
launcherStream.set(newStream);
|
||||||
|
await $userSettings.save();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Select.Trigger
|
||||||
|
class="border-theme-800 bg-theme-950 !text-muted-foreground font-semibold"
|
||||||
|
>
|
||||||
|
<div class="flex flex-row items-center gap-2 font-normal text-foreground">
|
||||||
|
{$launcherStream}
|
||||||
|
</div>
|
||||||
|
</Select.Trigger>
|
||||||
|
<Select.Content class="bg-theme-950 border border-theme-950 rounded-lg">
|
||||||
|
{#each $launcherStreams as stream (stream)}
|
||||||
|
<Select.Item value={stream}>
|
||||||
|
<div class="flex flex-row gap-2 items-center">
|
||||||
|
{stream}
|
||||||
|
</div>
|
||||||
|
</Select.Item>
|
||||||
|
{/each}
|
||||||
|
</Select.Content>
|
||||||
|
</Select.Root>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
currentSkin,
|
currentSkin,
|
||||||
currentView,
|
currentView,
|
||||||
firstStartup,
|
firstStartup,
|
||||||
|
launcherStream,
|
||||||
|
launcherStreams,
|
||||||
launcherVersion,
|
launcherVersion,
|
||||||
newVersion,
|
newVersion,
|
||||||
osuBuild,
|
osuBuild,
|
||||||
@@ -30,6 +32,7 @@
|
|||||||
import { currentUserInfo } from '@/data';
|
import { currentUserInfo } from '@/data';
|
||||||
import {
|
import {
|
||||||
getBeatmapSetsCount,
|
getBeatmapSetsCount,
|
||||||
|
getEZPPLauncherStreams,
|
||||||
getReleaseStream,
|
getReleaseStream,
|
||||||
getSkin,
|
getSkin,
|
||||||
getSkinsCount,
|
getSkinsCount,
|
||||||
@@ -148,6 +151,14 @@
|
|||||||
newVersion.set(launcherUpdate);
|
newVersion.set(launcherUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ezpplauncherStreams = await getEZPPLauncherStreams();
|
||||||
|
if (ezpplauncherStreams) launcherStreams.set(ezpplauncherStreams);
|
||||||
|
|
||||||
|
const selectedLauncherStream = $userSettings.value('patcherStream').get('stable');
|
||||||
|
if ($launcherStreams.includes(selectedLauncherStream)) {
|
||||||
|
launcherStream.set(selectedLauncherStream);
|
||||||
|
}
|
||||||
|
|
||||||
animate(ezppLogo, {
|
animate(ezppLogo, {
|
||||||
opacity: [1, 0],
|
opacity: [1, 0],
|
||||||
scale: [1, 1.05],
|
scale: [1, 1.05],
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
discordPresence,
|
discordPresence,
|
||||||
firstStartup,
|
firstStartup,
|
||||||
launcherVersion,
|
launcherVersion,
|
||||||
|
platform,
|
||||||
presenceLoading,
|
presenceLoading,
|
||||||
setupValues,
|
setupValues,
|
||||||
} from '@/global';
|
} from '@/global';
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
import { Toaster } from '@/components/ui/sonner';
|
import { Toaster } from '@/components/ui/sonner';
|
||||||
import { userAuth } from '@/userAuthentication';
|
import { userAuth } from '@/userAuthentication';
|
||||||
import { exit, getLauncherVersion, getPlatform } from '@/osuUtil';
|
import { encryptString, exit, getLauncherVersion, getPlatform } from '@/osuUtil';
|
||||||
import Button from '@/components/ui/button/button.svelte';
|
import Button from '@/components/ui/button/button.svelte';
|
||||||
import * as presence from '@/presence';
|
import * as presence from '@/presence';
|
||||||
|
|
||||||
@@ -87,10 +88,18 @@
|
|||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
window.Buffer = Buffer;
|
window.Buffer = Buffer;
|
||||||
|
|
||||||
|
/* const decryptTest = "AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAs463WdMtG0mr/mVLQCZ6dQAAAAAIAAAAUgBhAHcAAAAQZgAAAAEAACAAAABnyhFo8QK2iL5aTehKmsZSUpihGWBwlKfYj7cL2/lDagAAAAAOgAAAAAIAACAAAABMxyG6EdkLORSMB8isbltZhPQV2iVQ2r+yJLJ2Tw9yWiAAAABE1EzBPD9PRFQ3evk0vneNpfQTNTvMpjDVUTl3kAaKWUAAAADBshJzPDx6qcYfYh2zh6cKJWClZpIp6H50IKriW936XGhLFQboK/m18O77TBnpSrs0YosFjzsYVJTkrWjetFAf";
|
||||||
|
const decrypted = await decryptString(decryptTest);
|
||||||
|
console.log(decrypted); */
|
||||||
|
|
||||||
|
const encrypted = await encryptString("Todesengel007008009!", "cu24180ncjeiu0ci1nwui");
|
||||||
|
console.log(encrypted);
|
||||||
|
|
||||||
disableReload();
|
disableReload();
|
||||||
setupValues();
|
setupValues();
|
||||||
launcherVersion.set(await getLauncherVersion());
|
launcherVersion.set(await getLauncherVersion());
|
||||||
if ((await getPlatform()) !== 'windows') unsupported_platform = true;
|
platform.set(await getPlatform());
|
||||||
|
if ($platform !== "windows" && $platform !== "linux") unsupported_platform = true;
|
||||||
const isFirstStartup = await $userSettings.init();
|
const isFirstStartup = await $userSettings.init();
|
||||||
$userAuth.init();
|
$userAuth.init();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user