You've already forked AstralRinth
Merge commit '7fa442fb28a2b9156690ff147206275163e7aec8' into beta
This commit is contained in:
@@ -519,11 +519,14 @@ impl CacheValue {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, PartialEq, Eq, Debug, Copy, Clone)]
|
||||
#[derive(
|
||||
Deserialize, Serialize, PartialEq, Eq, Debug, Copy, Clone, Default,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CacheBehaviour {
|
||||
/// Serve expired data. If fetch fails / launcher is offline, errors are ignored
|
||||
/// and expired data is served
|
||||
#[default]
|
||||
StaleWhileRevalidateSkipOffline,
|
||||
// Serve expired data, revalidate in background
|
||||
StaleWhileRevalidate,
|
||||
@@ -533,12 +536,6 @@ pub enum CacheBehaviour {
|
||||
Bypass,
|
||||
}
|
||||
|
||||
impl Default for CacheBehaviour {
|
||||
fn default() -> Self {
|
||||
Self::StaleWhileRevalidateSkipOffline
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CachedEntry {
|
||||
id: String,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::ErrorKind;
|
||||
use crate::LAUNCHER_USER_AGENT;
|
||||
use crate::data::ModrinthCredentials;
|
||||
use crate::event::FriendPayload;
|
||||
use crate::event::emit::emit_friend;
|
||||
@@ -81,13 +83,9 @@ impl FriendsSocket {
|
||||
)
|
||||
.into_client_request()?;
|
||||
|
||||
let user_agent = format!(
|
||||
"modrinth/theseus/{} (support@modrinth.com)",
|
||||
env!("CARGO_PKG_VERSION")
|
||||
);
|
||||
request.headers_mut().insert(
|
||||
"User-Agent",
|
||||
HeaderValue::from_str(&user_agent).unwrap(),
|
||||
HeaderValue::from_str(LAUNCHER_USER_AGENT).unwrap(),
|
||||
);
|
||||
|
||||
let res = connect_async(request).await;
|
||||
@@ -322,7 +320,7 @@ impl FriendsSocket {
|
||||
exec: impl sqlx::Executor<'_, Database = sqlx::Sqlite> + Copy,
|
||||
semaphore: &FetchSemaphore,
|
||||
) -> crate::Result<()> {
|
||||
fetch_advanced(
|
||||
let result = fetch_advanced(
|
||||
Method::POST,
|
||||
&format!("{}friend/{user_id}", env!("MODRINTH_API_URL_V3")),
|
||||
None,
|
||||
@@ -332,7 +330,18 @@ impl FriendsSocket {
|
||||
semaphore,
|
||||
exec,
|
||||
)
|
||||
.await?;
|
||||
.await;
|
||||
|
||||
if let Err(ref e) = result
|
||||
&& let ErrorKind::LabrinthError(e) = &*e.raw
|
||||
&& e.error == "not_found"
|
||||
{
|
||||
return Err(ErrorKind::OtherError(format!(
|
||||
"No user found with username \"{user_id}\""
|
||||
))
|
||||
.into());
|
||||
}
|
||||
result?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ pub async fn init_watcher() -> crate::Result<FileWatcher> {
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
let span = tracing::span!(tracing::Level::INFO, "init_watcher");
|
||||
tracing::info!(parent: &span, "Initting watcher");
|
||||
tracing::info!(parent: &span, "Initing watcher");
|
||||
while let Some(res) = rx.recv().await {
|
||||
let _span = span.enter();
|
||||
|
||||
@@ -170,38 +170,22 @@ pub(crate) async fn watch_profile(
|
||||
let profile_path = dirs.profiles_dir().join(profile_path);
|
||||
|
||||
if profile_path.exists() && profile_path.is_dir() {
|
||||
for sub_path in ProjectType::iterator().map(|x| x.get_folder()).chain([
|
||||
"crash-reports",
|
||||
"saves",
|
||||
"servers.dat",
|
||||
]) {
|
||||
for sub_path in ProjectType::iterator()
|
||||
.map(|x| x.get_folder())
|
||||
.chain(["crash-reports", "saves"])
|
||||
{
|
||||
let full_path = profile_path.join(sub_path);
|
||||
|
||||
if !full_path.exists() && !full_path.is_symlink() {
|
||||
if !sub_path.contains(".") {
|
||||
if let Err(e) =
|
||||
crate::util::io::create_dir_all(&full_path).await
|
||||
{
|
||||
tracing::error!(
|
||||
"Failed to create directory for watcher {full_path:?}: {e}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else if sub_path == "servers.dat" {
|
||||
const EMPTY_NBT: &[u8] = &[
|
||||
10, // Compound tag
|
||||
0, 0, // Empty name
|
||||
0, // End of compound tag
|
||||
];
|
||||
if let Err(e) =
|
||||
crate::util::io::write(&full_path, EMPTY_NBT).await
|
||||
{
|
||||
tracing::error!(
|
||||
"Failed to create file for watcher {full_path:?}: {e}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if !full_path.exists()
|
||||
&& !full_path.is_symlink()
|
||||
&& !sub_path.contains(".")
|
||||
&& let Err(e) =
|
||||
crate::util::io::create_dir_all(&full_path).await
|
||||
{
|
||||
tracing::error!(
|
||||
"Failed to create directory for watcher {full_path:?}: {e}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut watcher = watcher.write().await;
|
||||
@@ -215,6 +199,16 @@ pub(crate) async fn watch_profile(
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut watcher = watcher.write().await;
|
||||
if let Err(e) = watcher
|
||||
.watcher()
|
||||
.watch(&profile_path, RecursiveMode::NonRecursive)
|
||||
{
|
||||
tracing::error!(
|
||||
"Failed to watch root profile directory for watcher {profile_path:?}: {e}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::event::emit::{emit_process, emit_profile};
|
||||
use crate::event::{ProcessPayloadType, ProfilePayloadType};
|
||||
use crate::profile;
|
||||
use crate::util::io::IOError;
|
||||
use crate::util::rpc::RpcServer;
|
||||
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
|
||||
use dashmap::DashMap;
|
||||
use quick_xml::Reader;
|
||||
@@ -15,7 +16,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::process::ExitStatus;
|
||||
use tempfile::TempDir;
|
||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||
use tokio::process::{Child, ChildStdin, Command};
|
||||
use tokio::process::{Child, Command};
|
||||
use uuid::Uuid;
|
||||
|
||||
const LAUNCHER_LOG_PATH: &str = "launcher_log.txt";
|
||||
@@ -46,9 +47,10 @@ impl ProcessManager {
|
||||
logs_folder: PathBuf,
|
||||
xml_logging: bool,
|
||||
main_class_keep_alive: TempDir,
|
||||
rpc_server: RpcServer,
|
||||
post_process_init: impl AsyncFnOnce(
|
||||
&ProcessMetadata,
|
||||
&mut ChildStdin,
|
||||
&RpcServer,
|
||||
) -> crate::Result<()>,
|
||||
) -> crate::Result<ProcessMetadata> {
|
||||
mc_command.stdout(std::process::Stdio::piped());
|
||||
@@ -67,14 +69,12 @@ impl ProcessManager {
|
||||
profile_path: profile_path.to_string(),
|
||||
},
|
||||
child: mc_proc,
|
||||
rpc_server,
|
||||
_main_class_keep_alive: main_class_keep_alive,
|
||||
};
|
||||
|
||||
if let Err(e) = post_process_init(
|
||||
&process.metadata,
|
||||
&mut process.child.stdin.as_mut().unwrap(),
|
||||
)
|
||||
.await
|
||||
if let Err(e) =
|
||||
post_process_init(&process.metadata, &process.rpc_server).await
|
||||
{
|
||||
tracing::error!("Failed to run post-process init: {e}");
|
||||
let _ = process.child.kill().await;
|
||||
@@ -165,6 +165,10 @@ impl ProcessManager {
|
||||
self.processes.get(&id).map(|x| x.metadata.clone())
|
||||
}
|
||||
|
||||
pub fn get_rpc(&self, id: Uuid) -> Option<RpcServer> {
|
||||
self.processes.get(&id).map(|x| x.rpc_server.clone())
|
||||
}
|
||||
|
||||
pub fn get_all(&self) -> Vec<ProcessMetadata> {
|
||||
self.processes
|
||||
.iter()
|
||||
@@ -215,6 +219,7 @@ struct Process {
|
||||
metadata: ProcessMetadata,
|
||||
child: Child,
|
||||
_main_class_keep_alive: TempDir,
|
||||
rpc_server: RpcServer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
||||
@@ -38,6 +38,10 @@ pub struct Settings {
|
||||
|
||||
pub developer_mode: bool,
|
||||
pub feature_flags: HashMap<FeatureFlag, bool>,
|
||||
|
||||
pub skipped_update: Option<String>,
|
||||
pub pending_update_toast_for_version: Option<String>,
|
||||
pub auto_download_updates: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, Hash, PartialEq)]
|
||||
@@ -63,7 +67,8 @@ impl Settings {
|
||||
json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,
|
||||
mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,
|
||||
hook_pre_launch, hook_wrapper, hook_post_exit,
|
||||
custom_dir, prev_custom_dir, migrated, json(feature_flags) feature_flags, toggle_sidebar
|
||||
custom_dir, prev_custom_dir, migrated, json(feature_flags) feature_flags, toggle_sidebar,
|
||||
skipped_update, pending_update_toast_for_version, auto_download_updates
|
||||
FROM settings
|
||||
"
|
||||
)
|
||||
@@ -117,6 +122,10 @@ impl Settings {
|
||||
.as_ref()
|
||||
.and_then(|x| serde_json::from_str(x).ok())
|
||||
.unwrap_or_default(),
|
||||
skipped_update: res.skipped_update,
|
||||
pending_update_toast_for_version: res
|
||||
.pending_update_toast_for_version,
|
||||
auto_download_updates: res.auto_download_updates.map(|x| x == 1),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -170,7 +179,11 @@ impl Settings {
|
||||
|
||||
toggle_sidebar = $26,
|
||||
feature_flags = $27,
|
||||
hide_nametag_skins_page = $28
|
||||
hide_nametag_skins_page = $28,
|
||||
|
||||
skipped_update = $29,
|
||||
pending_update_toast_for_version = $30,
|
||||
auto_download_updates = $31
|
||||
",
|
||||
max_concurrent_writes,
|
||||
max_concurrent_downloads,
|
||||
@@ -199,7 +212,10 @@ impl Settings {
|
||||
self.migrated,
|
||||
self.toggle_sidebar,
|
||||
feature_flags,
|
||||
self.hide_nametag_skins_page
|
||||
self.hide_nametag_skins_page,
|
||||
self.skipped_update,
|
||||
self.pending_update_toast_for_version,
|
||||
self.auto_download_updates,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
Reference in New Issue
Block a user