You've already forked AstralRinth
forked from didirus/AstralRinth
cleanup patches
This commit is contained in:
@@ -1,103 +0,0 @@
|
||||
diff --git a/packages/app-lib/src/state/db.rs b/packages/app-lib/src/state/db.rs
|
||||
index 14c53d81..607a345f 100644
|
||||
--- a/packages/app-lib/src/state/db.rs
|
||||
+++ b/packages/app-lib/src/state/db.rs
|
||||
@@ -3,6 +3,7 @@ use sqlx::sqlite::{
|
||||
SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions,
|
||||
};
|
||||
use sqlx::{Pool, Sqlite};
|
||||
+use tokio::time::Instant;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -17,8 +18,10 @@ pub(crate) async fn connect() -> crate::Result<Pool<Sqlite>> {
|
||||
crate::util::io::create_dir_all(&settings_dir).await?;
|
||||
}
|
||||
|
||||
- let uri = format!("sqlite:{}", settings_dir.join("app.db").display());
|
||||
+ let db_path = settings_dir.join("app.db");
|
||||
+ let db_exists = db_path.exists();
|
||||
|
||||
+ let uri = format!("sqlite:{}", db_path.display());
|
||||
let conn_options = SqliteConnectOptions::from_str(&uri)?
|
||||
.busy_timeout(Duration::from_secs(30))
|
||||
.journal_mode(SqliteJournalMode::Wal)
|
||||
@@ -30,10 +33,16 @@ pub(crate) async fn connect() -> crate::Result<Pool<Sqlite>> {
|
||||
.connect_with(conn_options)
|
||||
.await?;
|
||||
|
||||
- fix_migration_20240711194701(&pool).await?; // Patch by AstralRinth - 08.07.2025
|
||||
+ if db_exists {
|
||||
+ fix_modrinth_issued_migrations(&pool).await?;
|
||||
+ }
|
||||
|
||||
sqlx::migrate!().run(&pool).await?;
|
||||
|
||||
+ if !db_exists {
|
||||
+ fix_modrinth_issued_migrations(&pool).await?;
|
||||
+ }
|
||||
+
|
||||
if let Err(err) = stale_data_cleanup(&pool).await {
|
||||
tracing::warn!(
|
||||
"Failed to clean up stale data from state database: {err}"
|
||||
@@ -66,8 +75,17 @@ async fn stale_data_cleanup(pool: &Pool<Sqlite>) -> crate::Result<()> {
|
||||
}
|
||||
/*
|
||||
// Patch by AstralRinth - 08.07.2025
|
||||
+Problem files:
|
||||
+/packages/app-lib/migrations/20240711194701_init.sql !eol
|
||||
+/packages/app-lib/migrations/20240813205023_drop-active-unique.sql !eol
|
||||
+/packages/app-lib/migrations/20240930001852_disable-personalized-ads.sql !eol
|
||||
+/packages/app-lib/migrations/20241222013857_feature-flags.sql !eol
|
||||
*/
|
||||
-async fn fix_migration_20240711194701(pool: &Pool<Sqlite>) -> crate::Result<()> {
|
||||
+async fn fix_modrinth_issued_migrations(
|
||||
+ pool: &Pool<Sqlite>,
|
||||
+) -> crate::Result<()> {
|
||||
+ let started = Instant::now();
|
||||
+ tracing::info!("Fixing modrinth issued migrations");
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE "_sqlx_migrations"
|
||||
@@ -77,5 +95,41 @@ async fn fix_migration_20240711194701(pool: &Pool<Sqlite>) -> crate::Result<()>
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
+ tracing::info!("⚙️ Fixed first migration");
|
||||
+ sqlx::query(
|
||||
+ r#"
|
||||
+ UPDATE "_sqlx_migrations"
|
||||
+ SET checksum = X'5b53534a7ffd74eebede234222be47e1d37bd0cc5fee4475212491b0c0379c16e3079e08eee0af959b1fa20835eeb206'
|
||||
+ WHERE version = '20240813205023';
|
||||
+ "#,
|
||||
+ )
|
||||
+ .execute(pool)
|
||||
+ .await?;
|
||||
+ tracing::info!("⚙️ Fixed second migration");
|
||||
+ sqlx::query(
|
||||
+ r#"
|
||||
+ UPDATE "_sqlx_migrations"
|
||||
+ SET checksum = X'c0de804f171b5530010edae087a6e75645c0e90177e28365f935c9fdd9a5c68e24850b8c1498e386a379d525d520bc57'
|
||||
+ WHERE version = '20240930001852';
|
||||
+ "#,
|
||||
+ )
|
||||
+ .execute(pool)
|
||||
+ .await?;
|
||||
+ tracing::info!("⚙️ Fixed third migration");
|
||||
+ sqlx::query(
|
||||
+ r#"
|
||||
+ UPDATE "_sqlx_migrations"
|
||||
+ SET checksum = X'c17542cb989a0466153e695bfa4717f8970feee185ca186a2caa1f2f6c5d4adb990ab97c26cacfbbe09c39ac81551704'
|
||||
+ WHERE version = '20241222013857';
|
||||
+ "#,
|
||||
+ )
|
||||
+ .execute(pool)
|
||||
+ .await?;
|
||||
+ tracing::info!("⚙️ Fixed fourth migration");
|
||||
+ let elapsed = started.elapsed();
|
||||
+ tracing::info!(
|
||||
+ "✅ Fixed all known modrinth-issued migrations in {:.2?}",
|
||||
+ elapsed
|
||||
+ );
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,675 +0,0 @@
|
||||
diff --git a/apps/app-frontend/src/components/ui/AccountsCard.vue b/apps/app-frontend/src/components/ui/AccountsCard.vue
|
||||
index 7b03e1f39..69ee0e01e 100644
|
||||
--- a/apps/app-frontend/src/components/ui/AccountsCard.vue
|
||||
+++ b/apps/app-frontend/src/components/ui/AccountsCard.vue
|
||||
@@ -50,9 +50,8 @@
|
||||
color="primary"
|
||||
@click="login()"
|
||||
>
|
||||
- <LogInIcon v-if="!loginDisabled" />
|
||||
+ <MicrosoftIcon v-if="!loginDisabled"/>
|
||||
<SpinnerIcon v-else class="animate-spin" />
|
||||
- <MicrosoftIcon/>
|
||||
</Button>
|
||||
<Button v-tooltip="'Add offline'" icon-only @click="tryOfflineLogin()">
|
||||
<PirateIcon />
|
||||
diff --git a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
|
||||
index 7810581a3..ff16faadb 100644
|
||||
--- a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
|
||||
+++ b/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
type Version,
|
||||
} from '@modrinth/utils'
|
||||
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
||||
+import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||
import { get_project, get_version_many } from '@/helpers/cache'
|
||||
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
|
||||
import dayjs from 'dayjs'
|
||||
@@ -35,6 +36,11 @@ import type {
|
||||
Manifest,
|
||||
} from '../../../helpers/types'
|
||||
|
||||
+import { initAuthlibPatching } from '@/helpers/utils.js'
|
||||
+const authLibPatchingModal = ref(null)
|
||||
+const isAuthLibPatchedSuccess = ref(false)
|
||||
+const isAuthLibPatching = ref(false)
|
||||
+
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const repairConfirmModal = ref()
|
||||
@@ -447,9 +453,43 @@ const messages = defineMessages({
|
||||
defaultMessage: 'reinstall',
|
||||
},
|
||||
})
|
||||
+
|
||||
+async function handleInitAuthLibPatching(ismojang: boolean) {
|
||||
+ isAuthLibPatching.value = true
|
||||
+ let state = false
|
||||
+ let instance_path = props.instance.loader_version != null ? props.instance.game_version + "-" + props.instance.loader_version : props.instance.game_version
|
||||
+ try {
|
||||
+ state = await initAuthlibPatching(instance_path, ismojang)
|
||||
+ } catch (err) {
|
||||
+ console.error(err)
|
||||
+ }
|
||||
+ isAuthLibPatching.value = false
|
||||
+ isAuthLibPatchedSuccess.value = state
|
||||
+ authLibPatchingModal.value.show()
|
||||
+}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
+ <ModalWrapper
|
||||
+ ref="authLibPatchingModal"
|
||||
+ :header="'AuthLib installation report'"
|
||||
+ :closable="true"
|
||||
+ @close="authLibPatchingModal.hide()"
|
||||
+ >
|
||||
+ <div class="modal-body">
|
||||
+ <h2 class="text-lg font-bold text-contrast space-y-2">
|
||||
+ <p class="flex items-center gap-2 neon-text">
|
||||
+ <span v-if="isAuthLibPatchedSuccess" class="neon-text">
|
||||
+ AuthLib installation completed successfully! Now you can log in and play!
|
||||
+ </span>
|
||||
+ <span v-else class="neon-text">
|
||||
+ Failed to install AuthLib. It's possible that no compatible AuthLib version was found for the selected game and/or mod loader version.
|
||||
+ There may also be a problem with accessing resources behind CloudFlare.
|
||||
+ </span>
|
||||
+ </p>
|
||||
+ </h2>
|
||||
+ </div>
|
||||
+ </ModalWrapper>
|
||||
<ConfirmModalWrapper
|
||||
ref="repairConfirmModal"
|
||||
:title="formatMessage(messages.repairConfirmTitle)"
|
||||
@@ -720,6 +760,24 @@ const messages = defineMessages({
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
+ <h2 class="m-0 mt-4 text-lg font-extrabold text-contrast block">
|
||||
+ <div v-if="isAuthLibPatching" class="w-6 h-6 cursor-pointer hover:brightness-75 neon-icon pulse">
|
||||
+ <SpinnerIcon class="size-4 animate-spin" />
|
||||
+ </div>
|
||||
+ Auth system (Skins) <span class="text-sm font-bold px-2 bg-brand-highlight text-brand rounded-full">Beta</span>
|
||||
+ </h2>
|
||||
+ <div class="mt-4 flex gap-2">
|
||||
+ <ButtonStyled class="neon-button neon">
|
||||
+ <button :disabled="isAuthLibPatching" @click="handleInitAuthLibPatching(true)">
|
||||
+ Install Microsoft
|
||||
+ </button>
|
||||
+ </ButtonStyled>
|
||||
+ <ButtonStyled class="neon-button neon">
|
||||
+ <button :disabled="isAuthLibPatching" @click="handleInitAuthLibPatching(false) ">
|
||||
+ Install Ely.By
|
||||
+ </button>
|
||||
+ </ButtonStyled>
|
||||
+ </div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-if="instance.linked_data && instance.linked_data.locked">
|
||||
@@ -787,3 +845,9 @@ const messages = defineMessages({
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
+
|
||||
+<style lang="scss" scoped>
|
||||
+@import '../../../../../../packages/assets/styles/neon-button.scss';
|
||||
+@import '../../../../../../packages/assets/styles/neon-text.scss';
|
||||
+@import '../../../../../../packages/assets/styles/neon-icon.scss';
|
||||
+</style>
|
||||
\ No newline at end of file
|
||||
diff --git a/apps/app-frontend/src/helpers/update.js b/apps/app-frontend/src/helpers/update.js
|
||||
index cea6c6bd4..f7033b7ac 100644
|
||||
--- a/apps/app-frontend/src/helpers/update.js
|
||||
+++ b/apps/app-frontend/src/helpers/update.js
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref } from 'vue'
|
||||
import { getVersion } from '@tauri-apps/api/app'
|
||||
-import { getArtifact, getOS } from '@/helpers/utils.js'
|
||||
+import { initUpdateLauncher, getOS } from '@/helpers/utils.js'
|
||||
|
||||
export const allowState = ref(false)
|
||||
export const installState = ref(false)
|
||||
@@ -52,7 +52,7 @@ export async function getRemote(isDownloadState) {
|
||||
installState.value = true;
|
||||
const builds = remoteData.assets;
|
||||
const fileName = getInstaller(getExtension(), builds);
|
||||
- result = fileName ? await getArtifact(fileName[1], fileName[0], currentOS.value, true) : false;
|
||||
+ result = fileName ? await initUpdateLauncher(fileName[1], fileName[0], currentOS.value, true) : false;
|
||||
installState.value = false;
|
||||
}
|
||||
|
||||
diff --git a/apps/app-frontend/src/helpers/utils.js b/apps/app-frontend/src/helpers/utils.js
|
||||
index ac950e175..99cbde38f 100644
|
||||
--- a/apps/app-frontend/src/helpers/utils.js
|
||||
+++ b/apps/app-frontend/src/helpers/utils.js
|
||||
@@ -11,9 +11,9 @@ export async function getOS() {
|
||||
}
|
||||
|
||||
// [AR] Feature
|
||||
-export async function getArtifact(downloadurl, filename, ostype, autoupdatesupported) {
|
||||
+export async function initUpdateLauncher(downloadurl, filename, ostype, autoupdatesupported) {
|
||||
console.log('Downloading build', downloadurl, filename, ostype, autoupdatesupported)
|
||||
- return await invoke('plugin:utils|get_artifact', { downloadurl, filename, ostype, autoupdatesupported })
|
||||
+ return await invoke('plugin:utils|init_update_launcher', { downloadurl, filename, ostype, autoupdatesupported })
|
||||
}
|
||||
|
||||
// [AR] Patch fix
|
||||
@@ -21,6 +21,11 @@ export async function applyMigrationFix(eol) {
|
||||
return await invoke('plugin:utils|apply_migration_fix', { eol })
|
||||
}
|
||||
|
||||
+// [AR] Feature
|
||||
+export async function initAuthlibPatching(minecraftversion, ismojang) {
|
||||
+ return await invoke('plugin:utils|init_authlib_patching', { minecraftversion, ismojang })
|
||||
+}
|
||||
+
|
||||
export async function openPath(path) {
|
||||
return await invoke('plugin:utils|open_path', { path })
|
||||
}
|
||||
diff --git a/apps/app/build.rs b/apps/app/build.rs
|
||||
index 4942497aa..5a35c88df 100644
|
||||
--- a/apps/app/build.rs
|
||||
+++ b/apps/app/build.rs
|
||||
@@ -218,8 +218,9 @@ fn main() {
|
||||
"utils",
|
||||
InlinedPlugin::new()
|
||||
.commands(&[
|
||||
+ "init_authlib_patching",
|
||||
"apply_migration_fix",
|
||||
- "get_artifact",
|
||||
+ "init_update_launcher",
|
||||
"get_os",
|
||||
"should_disable_mouseover",
|
||||
"highlight_in_folder",
|
||||
diff --git a/apps/app/src/api/utils.rs b/apps/app/src/api/utils.rs
|
||||
index 452079157..951affa63 100644
|
||||
--- a/apps/app/src/api/utils.rs
|
||||
+++ b/apps/app/src/api/utils.rs
|
||||
@@ -10,14 +10,15 @@ use crate::api::{Result, TheseusSerializableError};
|
||||
use dashmap::DashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use theseus::prelude::canonicalize;
|
||||
-use url::Url;
|
||||
use theseus::util::utils;
|
||||
+use url::Url;
|
||||
|
||||
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||
tauri::plugin::Builder::new("utils")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
+ init_authlib_patching,
|
||||
apply_migration_fix,
|
||||
- get_artifact,
|
||||
+ init_update_launcher,
|
||||
get_os,
|
||||
should_disable_mouseover,
|
||||
highlight_in_folder,
|
||||
@@ -29,6 +30,17 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||
.build()
|
||||
}
|
||||
|
||||
+/// [AR] Feature
|
||||
+#[tauri::command]
|
||||
+pub async fn init_authlib_patching(
|
||||
+ minecraftversion: &str,
|
||||
+ ismojang: bool,
|
||||
+) -> Result<bool> {
|
||||
+ let result =
|
||||
+ utils::init_authlib_patching(minecraftversion, ismojang).await?;
|
||||
+ Ok(result)
|
||||
+}
|
||||
+
|
||||
/// [AR] Patch fix
|
||||
#[tauri::command]
|
||||
pub async fn apply_migration_fix(eol: &str) -> Result<bool> {
|
||||
@@ -38,8 +50,19 @@ pub async fn apply_migration_fix(eol: &str) -> Result<bool> {
|
||||
|
||||
/// [AR] Feature
|
||||
#[tauri::command]
|
||||
-pub async fn get_artifact(downloadurl: &str, filename: &str, ostype: &str, autoupdatesupported: bool) -> Result<()> {
|
||||
- let _ = utils::init_download(downloadurl, filename, ostype, autoupdatesupported).await;
|
||||
+pub async fn init_update_launcher(
|
||||
+ downloadurl: &str,
|
||||
+ filename: &str,
|
||||
+ ostype: &str,
|
||||
+ autoupdatesupported: bool,
|
||||
+) -> Result<()> {
|
||||
+ let _ = utils::init_update_launcher(
|
||||
+ downloadurl,
|
||||
+ filename,
|
||||
+ ostype,
|
||||
+ autoupdatesupported,
|
||||
+ )
|
||||
+ .await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
diff --git a/apps/app/tauri.conf.json b/apps/app/tauri.conf.json
|
||||
index 4ebb2aa5f..cfc271565 100644
|
||||
--- a/apps/app/tauri.conf.json
|
||||
+++ b/apps/app/tauri.conf.json
|
||||
@@ -41,7 +41,7 @@
|
||||
]
|
||||
},
|
||||
"productName": "AstralRinth App",
|
||||
- "version": "0.10.303",
|
||||
+ "version": "0.10.304",
|
||||
"mainBinaryName": "AstralRinth App",
|
||||
"identifier": "AstralRinthApp",
|
||||
"plugins": {
|
||||
diff --git a/packages/app-lib/src/error.rs b/packages/app-lib/src/error.rs
|
||||
index 75c144f55..360984efd 100644
|
||||
--- a/packages/app-lib/src/error.rs
|
||||
+++ b/packages/app-lib/src/error.rs
|
||||
@@ -151,6 +151,41 @@ pub enum ErrorKind {
|
||||
"A skin texture must have a dimension of either 64x64 or 64x32 pixels"
|
||||
)]
|
||||
InvalidSkinTexture,
|
||||
+
|
||||
+ #[error(
|
||||
+ "[AR] Target minecraft {minecraft_version} version doesn't exist."
|
||||
+ )]
|
||||
+ InvalidMinecraftVersion {
|
||||
+ minecraft_version: String,
|
||||
+ },
|
||||
+
|
||||
+ #[error(
|
||||
+ "[AR] Target metadata not found for minecraft version {minecraft_version}."
|
||||
+ )]
|
||||
+ MinecraftMetadataNotFound {
|
||||
+ minecraft_version: String,
|
||||
+ },
|
||||
+
|
||||
+ #[error(
|
||||
+ "[AR] Network error: {error}"
|
||||
+ )]
|
||||
+ NetworkErrorOccurred {
|
||||
+ error: String,
|
||||
+ },
|
||||
+
|
||||
+ #[error(
|
||||
+ "[AR] IO error: {error}"
|
||||
+ )]
|
||||
+ IOErrorOccurred {
|
||||
+ error: String,
|
||||
+ },
|
||||
+
|
||||
+ #[error(
|
||||
+ "[AR] Parse error: {reason}"
|
||||
+ )]
|
||||
+ ParseError {
|
||||
+ reason: String,
|
||||
+ },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
diff --git a/packages/app-lib/src/launcher/mod.rs b/packages/app-lib/src/launcher/mod.rs
|
||||
index f1b5deb85..a7d0708e3 100644
|
||||
--- a/packages/app-lib/src/launcher/mod.rs
|
||||
+++ b/packages/app-lib/src/launcher/mod.rs
|
||||
@@ -633,6 +633,7 @@ pub async fn launch_minecraft(
|
||||
command.arg("--add-opens=jdk.internal/jdk.internal.misc=ALL-UNNAMED");
|
||||
}
|
||||
|
||||
+ // FIXME: Fix ElyBy integration with this patch.
|
||||
// [AR] Patch
|
||||
if credentials.access_token == "null" && credentials.refresh_token == "null" {
|
||||
if version_jar == "1.16.4" || version_jar == "1.16.5" {
|
||||
diff --git a/packages/app-lib/src/util/utils.rs b/packages/app-lib/src/util/utils.rs
|
||||
index adebc3a67..e4d9a2ab1 100644
|
||||
--- a/packages/app-lib/src/util/utils.rs
|
||||
+++ b/packages/app-lib/src/util/utils.rs
|
||||
@@ -1,12 +1,12 @@
|
||||
-///
|
||||
-/// [AR] Feature
|
||||
-///
|
||||
-use crate::Result;
|
||||
use crate::api::update;
|
||||
use crate::state::db;
|
||||
+///
|
||||
+/// [AR] Feature Utils
|
||||
+///
|
||||
+use crate::{Result, State};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::process;
|
||||
-use tokio::io;
|
||||
+use tokio::{fs, io};
|
||||
|
||||
const PACKAGE_JSON_CONTENT: &str =
|
||||
// include_str!("../../../../apps/app-frontend/package.json");
|
||||
@@ -17,13 +17,311 @@ pub struct Launcher {
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
+#[derive(Debug, Deserialize)]
|
||||
+struct Artifact {
|
||||
+ path: Option<String>,
|
||||
+ sha1: Option<String>,
|
||||
+ url: Option<String>,
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug, Deserialize)]
|
||||
+struct Downloads {
|
||||
+ artifact: Option<Artifact>,
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug, Deserialize)]
|
||||
+struct Library {
|
||||
+ name: String,
|
||||
+ downloads: Option<Downloads>,
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug, Deserialize)]
|
||||
+struct VersionJson {
|
||||
+ libraries: Vec<Library>,
|
||||
+}
|
||||
+
|
||||
+/// Deserialize the content of package.json into a Launcher struct
|
||||
pub fn read_package_json() -> io::Result<Launcher> {
|
||||
- // Deserialize the content of package.json into a Launcher struct
|
||||
let launcher: Launcher = serde_json::from_str(PACKAGE_JSON_CONTENT)?;
|
||||
-
|
||||
Ok(launcher)
|
||||
}
|
||||
|
||||
+/// ### AR • Universal Write (IO) Function
|
||||
+/// Saves the downloaded bytes to the `libraries` directory using the given relative path.
|
||||
+async fn write_file_to_libraries(
|
||||
+ relative_path: &str,
|
||||
+ bytes: &bytes::Bytes,
|
||||
+) -> Result<()> {
|
||||
+ let state = State::get().await?;
|
||||
+ let output_path = state.directories.libraries_dir().join(relative_path);
|
||||
+
|
||||
+ fs::write(&output_path, bytes).await.map_err(|e| {
|
||||
+ tracing::error!("[AR] • Failed to save file: {:?}", e);
|
||||
+ crate::ErrorKind::IOErrorOccurred {
|
||||
+ error: format!("Failed to save file: {e}"),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
+/// ### AR • AuthLib (Ely By)
|
||||
+/// Initializes the AuthLib patching process.
|
||||
+///
|
||||
+/// Returns `true` if the authlib patched successfully.
|
||||
+pub async fn init_authlib_patching(
|
||||
+ minecraft_version: &str,
|
||||
+ is_mojang: bool,
|
||||
+) -> Result<bool> {
|
||||
+ let minecraft_library_metadata = get_minecraft_library_metadata(minecraft_version).await?;
|
||||
+ // Parses the AuthLib version from string
|
||||
+ // Example output: "com.mojang:authlib:6.0.58" -> "6.0.58"
|
||||
+ let authlib_version = minecraft_library_metadata.name.split(':').nth(2).unwrap_or("unknown");
|
||||
+
|
||||
+ tracing::info!(
|
||||
+ "[AR] • Attempting to download AuthLib {}.",
|
||||
+ authlib_version
|
||||
+ );
|
||||
+
|
||||
+ download_authlib(
|
||||
+ &minecraft_library_metadata,
|
||||
+ authlib_version,
|
||||
+ minecraft_version,
|
||||
+ is_mojang,
|
||||
+ )
|
||||
+ .await
|
||||
+}
|
||||
+
|
||||
+/// ### AR • AuthLib (Ely By)
|
||||
+/// Downloads the AuthLib file from Mojang libraries or Git Astralium services.
|
||||
+async fn download_authlib(
|
||||
+ minecraft_library_metadata: &Library,
|
||||
+ authlib_version: &str,
|
||||
+ minecraft_version: &str,
|
||||
+ is_mojang: bool,
|
||||
+) -> Result<bool> {
|
||||
+ let state = State::get().await?;
|
||||
+ let (url, path) = extract_download_info(minecraft_library_metadata, minecraft_version)?;
|
||||
+ let mut download_url = url.to_string();
|
||||
+ let full_path = state.directories.libraries_dir().join(path);
|
||||
+
|
||||
+ if !is_mojang {
|
||||
+ tracing::info!(
|
||||
+ "[AR] • Attempting to download AuthLib from Git Astralium"
|
||||
+ );
|
||||
+ download_url = extract_ely_authlib_url(authlib_version).await?;
|
||||
+ }
|
||||
+ tracing::info!("[AR] • Downloading AuthLib from URL: {}", download_url);
|
||||
+ let bytes = fetch_bytes_from_url(&download_url).await?;
|
||||
+ tracing::info!("[AR] • Will save to path: {}", full_path.to_str().unwrap());
|
||||
+ write_file_to_libraries(full_path.to_str().unwrap(), &bytes).await?;
|
||||
+ tracing::info!("[AR] • Successfully saved AuthLib to {:?}", full_path);
|
||||
+ Ok(true)
|
||||
+}
|
||||
+
|
||||
+/// ### AR • AuthLib (Ely By)
|
||||
+/// Parses the ElyIntegration release JSON and returns the download URL for the given AuthLib version.
|
||||
+async fn extract_ely_authlib_url(authlib_version: &str) -> Result<String> {
|
||||
+ let url = "https://git.astralium.su/api/v1/repos/didirus/ElyIntegration/releases/latest";
|
||||
+
|
||||
+ let response = reqwest::get(url).await.map_err(|e| {
|
||||
+ tracing::error!(
|
||||
+ "[AR] • Failed to fetch ElyIntegration release JSON: {:?}",
|
||||
+ e
|
||||
+ );
|
||||
+ crate::ErrorKind::NetworkErrorOccurred {
|
||||
+ error: format!("Failed to fetch ElyIntegration release JSON: {}", e),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ let json: serde_json::Value = response.json().await.map_err(|e| {
|
||||
+ tracing::error!("[AR] • Failed to parse ElyIntegration JSON: {:?}", e);
|
||||
+ crate::ErrorKind::ParseError {
|
||||
+ reason: format!("Failed to parse ElyIntegration JSON: {}", e),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ let assets =
|
||||
+ json.get("assets")
|
||||
+ .and_then(|v| v.as_array())
|
||||
+ .ok_or_else(|| {
|
||||
+ crate::ErrorKind::ParseError {
|
||||
+ reason: "Missing 'assets' array".into(),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ let asset = assets
|
||||
+ .iter()
|
||||
+ .find(|a| {
|
||||
+ a.get("name")
|
||||
+ .and_then(|n| n.as_str())
|
||||
+ .map(|n| n.contains(authlib_version))
|
||||
+ .unwrap_or(false)
|
||||
+ })
|
||||
+ .ok_or_else(|| {
|
||||
+ crate::ErrorKind::ParseError {
|
||||
+ reason: format!(
|
||||
+ "No matching asset for authlib-{}.jar",
|
||||
+ authlib_version
|
||||
+ ),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ let download_url = asset
|
||||
+ .get("browser_download_url")
|
||||
+ .and_then(|u| u.as_str())
|
||||
+ .ok_or_else(|| {
|
||||
+ crate::ErrorKind::ParseError {
|
||||
+ reason: "Missing 'browser_download_url'".into(),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ Ok(download_url.to_string())
|
||||
+}
|
||||
+
|
||||
+/// ### AR • AuthLib (Ely By)
|
||||
+/// Extracts the artifact URL and Path from the library structure.
|
||||
+///
|
||||
+/// Returns a tuple of references to the URL and path strings,
|
||||
+/// or an error if the required metadata is missing.
|
||||
+fn extract_download_info<'a>(
|
||||
+ minecraft_library_metadata: &'a Library,
|
||||
+ minecraft_version: &str,
|
||||
+) -> Result<(&'a str, &'a str)> {
|
||||
+ let artifact = minecraft_library_metadata
|
||||
+ .downloads
|
||||
+ .as_ref()
|
||||
+ .and_then(|d| d.artifact.as_ref())
|
||||
+ .ok_or_else(|| {
|
||||
+ crate::ErrorKind::MinecraftMetadataNotFound {
|
||||
+ minecraft_version: minecraft_version.to_string(),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ let url = artifact.url.as_deref().ok_or_else(|| {
|
||||
+ crate::ErrorKind::MinecraftMetadataNotFound {
|
||||
+ minecraft_version: minecraft_version.to_string(),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ let path = artifact.path.as_deref().ok_or_else(|| {
|
||||
+ crate::ErrorKind::MinecraftMetadataNotFound {
|
||||
+ minecraft_version: minecraft_version.to_string(),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ Ok((url, path))
|
||||
+}
|
||||
+
|
||||
+/// ### AR • AuthLib (Ely By)
|
||||
+/// Downloads bytes from the provided URL with a 15 second timeout.
|
||||
+async fn fetch_bytes_from_url(url: &str) -> Result<bytes::Bytes> {
|
||||
+ // Create client instance with request timeout.
|
||||
+ let client = reqwest::Client::new();
|
||||
+ const TIMEOUT_SECONDS: u64 = 15;
|
||||
+
|
||||
+ let response = tokio::time::timeout(
|
||||
+ std::time::Duration::from_secs(TIMEOUT_SECONDS),
|
||||
+ client.get(url).send(),
|
||||
+ )
|
||||
+ .await
|
||||
+ .map_err(|_| {
|
||||
+ tracing::error!("[AR] • Download timed out after {} seconds", TIMEOUT_SECONDS);
|
||||
+ crate::ErrorKind::NetworkErrorOccurred {
|
||||
+ error: format!("Download timed out after {TIMEOUT_SECONDS} seconds").to_string(),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?
|
||||
+ .map_err(|e| {
|
||||
+ tracing::error!("[AR] • Request error: {:?}", e);
|
||||
+ crate::ErrorKind::NetworkErrorOccurred {
|
||||
+ error: format!("Request error: {e}"),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })?;
|
||||
+
|
||||
+ if !response.status().is_success() {
|
||||
+ let status = response.status().to_string();
|
||||
+ tracing::error!("[AR] • Failed to download authlib: HTTP {}", status);
|
||||
+ return Err(crate::ErrorKind::NetworkErrorOccurred {
|
||||
+ error: format!("Failed to download authlib: HTTP {status}"),
|
||||
+ }
|
||||
+ .as_error());
|
||||
+ }
|
||||
+
|
||||
+ response.bytes().await.map_err(|e| {
|
||||
+ tracing::error!("[AR] • Failed to read response bytes: {:?}", e);
|
||||
+ crate::ErrorKind::NetworkErrorOccurred {
|
||||
+ error: format!("Failed to read response bytes: {e}"),
|
||||
+ }
|
||||
+ .as_error()
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
+/// ### AR • AuthLib (Ely By)
|
||||
+/// Gets the Minecraft library metadata from the local libraries directory.
|
||||
+async fn get_minecraft_library_metadata(minecraft_version: &str) -> Result<Library> {
|
||||
+ let state = State::get().await?;
|
||||
+
|
||||
+ let path = state
|
||||
+ .directories
|
||||
+ .version_dir(minecraft_version)
|
||||
+ .join(format!("{}.json", minecraft_version));
|
||||
+ if !path.exists() {
|
||||
+ tracing::error!("[AR] • File not found: {:#?}", path);
|
||||
+ return Err(crate::ErrorKind::InvalidMinecraftVersion {
|
||||
+ minecraft_version: minecraft_version.to_string(),
|
||||
+ }
|
||||
+ .as_error());
|
||||
+ }
|
||||
+
|
||||
+ let content = fs::read_to_string(&path).await?;
|
||||
+ let version_data: VersionJson = serde_json::from_str(&content)?;
|
||||
+
|
||||
+ for lib in version_data.libraries {
|
||||
+ if lib.name.contains("com.mojang:authlib") {
|
||||
+ if let Some(downloads) = &lib.downloads {
|
||||
+ if let Some(artifact) = &downloads.artifact {
|
||||
+ if artifact.path.is_some()
|
||||
+ && artifact.url.is_some()
|
||||
+ && artifact.sha1.is_some()
|
||||
+ {
|
||||
+ tracing::info!("[AR] • Found AuthLib: {}", lib.name);
|
||||
+ tracing::info!(
|
||||
+ "[AR] • Path: {}",
|
||||
+ artifact.path.as_ref().unwrap()
|
||||
+ );
|
||||
+ tracing::info!(
|
||||
+ "[AR] • URL: {}",
|
||||
+ artifact.url.as_ref().unwrap()
|
||||
+ );
|
||||
+ tracing::info!(
|
||||
+ "[AR] • SHA1: {}",
|
||||
+ artifact.sha1.as_ref().unwrap()
|
||||
+ );
|
||||
+
|
||||
+ return Ok(lib);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Err(crate::ErrorKind::MinecraftMetadataNotFound {
|
||||
+ minecraft_version: minecraft_version.to_string(),
|
||||
+ }
|
||||
+ .as_error())
|
||||
+}
|
||||
+
|
||||
+/// ### AR • Migration
|
||||
+/// Applying migration fix for SQLite database.
|
||||
pub async fn apply_migration_fix(eol: &str) -> Result<bool> {
|
||||
tracing::info!("[AR] • Attempting to apply migration fix");
|
||||
let patched = db::apply_migration_fix(eol).await?;
|
||||
@@ -35,14 +333,19 @@ pub async fn apply_migration_fix(eol: &str) -> Result<bool> {
|
||||
Ok(patched)
|
||||
}
|
||||
|
||||
-pub async fn init_download(
|
||||
+/// ### AR • Updater
|
||||
+/// Initialize the update launcher.
|
||||
+pub async fn init_update_launcher(
|
||||
download_url: &str,
|
||||
local_filename: &str,
|
||||
os_type: &str,
|
||||
auto_update_supported: bool,
|
||||
) -> Result<()> {
|
||||
- println!("[AR] • Initialize downloading from • {:?}", download_url);
|
||||
- println!("[AR] • Save local file name • {:?}", local_filename);
|
||||
+ tracing::info!("[AR] • Initialize downloading from • {:?}", download_url);
|
||||
+ tracing::info!("[AR] • Save local file name • {:?}", local_filename);
|
||||
+ tracing::info!("[AR] • OS type • {}", os_type);
|
||||
+ tracing::info!("[AR] • Auto update supported • {}", auto_update_supported);
|
||||
+
|
||||
if let Err(e) = update::get_resource(
|
||||
download_url,
|
||||
local_filename,
|
||||
@@ -1,26 +0,0 @@
|
||||
diff --git a/apps/app-frontend/src/components/ui/InstanceCreationModal.vue b/apps/app-frontend/src/components/ui/InstanceCreationModal.vue
|
||||
index 9333a75a..e439c203 100644
|
||||
--- a/apps/app-frontend/src/components/ui/InstanceCreationModal.vue
|
||||
+++ b/apps/app-frontend/src/components/ui/InstanceCreationModal.vue
|
||||
@@ -379,7 +379,7 @@ const upload_icon = async () => {
|
||||
],
|
||||
})
|
||||
|
||||
- icon.value = res ? res.path : null
|
||||
+ icon.value = res ? res : null
|
||||
|
||||
if (!icon.value) return
|
||||
display_icon.value = convertFileSrc(icon.value)
|
||||
diff --git a/apps/app-frontend/src/pages/instance/Options.vue b/apps/app-frontend/src/pages/instance/Options.vue
|
||||
index e4166eab..9ca84390 100644
|
||||
--- a/apps/app-frontend/src/pages/instance/Options.vue
|
||||
+++ b/apps/app-frontend/src/pages/instance/Options.vue
|
||||
@@ -581,7 +581,7 @@ async function setIcon() {
|
||||
|
||||
if (!value) return
|
||||
|
||||
- icon.value = value.path
|
||||
+ icon.value = value
|
||||
await edit_icon(props.instance.path, icon.value).catch(handleError)
|
||||
|
||||
trackEvent('InstanceSetIcon')
|
||||
File diff suppressed because one or more lines are too long
@@ -1,22 +0,0 @@
|
||||
diff --git a/packages/app-lib/src/api/profile/mod.rs b/packages/app-lib/src/api/profile/mod.rs
|
||||
index aaa2864a..7addca68 100644
|
||||
--- a/packages/app-lib/src/api/profile/mod.rs
|
||||
+++ b/packages/app-lib/src/api/profile/mod.rs
|
||||
@@ -845,7 +845,7 @@ pub async fn create_mrpack_json(
|
||||
)
|
||||
.await?;
|
||||
|
||||
- let files = projects
|
||||
+ let mut files = projects
|
||||
.into_iter()
|
||||
.filter_map(|(path, version_id)| {
|
||||
if let Some(version) = versions.iter().find(|x| x.id == version_id)
|
||||
@@ -890,6 +890,8 @@ pub async fn create_mrpack_json(
|
||||
})
|
||||
.collect::<crate::Result<Vec<PackFile>>>()?;
|
||||
|
||||
+ files.sort_by(|a, b| a.path.cmp(&b.path));
|
||||
+
|
||||
Ok(PackFormat {
|
||||
game: "minecraft".to_string(),
|
||||
format_version: 1,
|
||||
1214
patches/pr-10.patch
1214
patches/pr-10.patch
File diff suppressed because it is too large
Load Diff
@@ -1,46 +0,0 @@
|
||||
diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs
|
||||
index 6d429ffb..f261561f 100644
|
||||
--- a/apps/app/src/main.rs
|
||||
+++ b/apps/app/src/main.rs
|
||||
@@ -188,7 +188,20 @@ fn main() {
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(
|
||||
tauri_plugin_window_state::Builder::default()
|
||||
- .with_filename("app-window-state.json")
|
||||
+ .with_filename(
|
||||
+ if std::env::current_dir()
|
||||
+ .ok()
|
||||
+ .map(|dir| dir.join("portable.txt").exists())
|
||||
+ .unwrap_or(false)
|
||||
+ {
|
||||
+ std::env::current_dir()
|
||||
+ .ok()
|
||||
+ .map(|dir| dir.join("UserData/app-window-state.json").to_string_lossy().into_owned())
|
||||
+ .unwrap()
|
||||
+ } else {
|
||||
+ "app-window-state.json".to_string()
|
||||
+ },
|
||||
+ )
|
||||
.build(),
|
||||
)
|
||||
.setup(|app| {
|
||||
diff --git a/packages/app-lib/src/state/dirs.rs b/packages/app-lib/src/state/dirs.rs
|
||||
index 96148a91..038313d6 100644
|
||||
--- a/packages/app-lib/src/state/dirs.rs
|
||||
+++ b/packages/app-lib/src/state/dirs.rs
|
||||
@@ -23,8 +23,13 @@ impl DirectoryInfo {
|
||||
// Get the settings directory
|
||||
// init() is not needed for this function
|
||||
pub fn get_initial_settings_dir() -> Option<PathBuf> {
|
||||
- Self::env_path("THESEUS_CONFIG_DIR")
|
||||
- .or_else(|| Some(dirs::data_dir()?.join("AstralRinthApp")))
|
||||
+ Self::env_path("THESEUS_CONFIG_DIR").or_else(|| {
|
||||
+ if std::env::current_dir().ok()?.join("portable.txt").exists() {
|
||||
+ Some(std::path::Path::new("UserData").to_path_buf())
|
||||
+ } else {
|
||||
+ Some(dirs::data_dir()?.join("AstralRinthApp"))
|
||||
+ }
|
||||
+ })
|
||||
}
|
||||
|
||||
/// Get all paths needed for Theseus to operate properly
|
||||
Reference in New Issue
Block a user