summaryrefslogtreecommitdiffstats
path: root/src/launcher/settings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/launcher/settings.rs')
-rw-r--r--src/launcher/settings.rs232
1 files changed, 0 insertions, 232 deletions
diff --git a/src/launcher/settings.rs b/src/launcher/settings.rs
deleted file mode 100644
index 8453653..0000000
--- a/src/launcher/settings.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-use std::collections::HashMap;
-use std::error::Error;
-use std::fmt::{Display, Formatter};
-use std::io::ErrorKind;
-use std::path::{Path, PathBuf};
-use log::warn;
-use serde::{Deserialize, Serialize};
-use tokio::{fs, io};
-use tokio::fs::File;
-use tokio::io::AsyncWriteExt;
-use super::constants;
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-struct SettingsInner {
- profiles: HashMap<String, Profile>,
- instances: HashMap<String, Instance>
-}
-
-pub struct Settings {
- path: Option<PathBuf>,
- inner: SettingsInner
-}
-
-#[derive(Debug)]
-pub enum SettingsError {
- IO { what: &'static str, error: io::Error },
- Format(serde_json::Error),
- Inconsistent(String)
-}
-
-impl Display for SettingsError {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- SettingsError::IO { what, error } => write!(f, "settings i/o error ({}): {}", what, error),
- SettingsError::Format(err) => write!(f, "settings format error: {}", err),
- SettingsError::Inconsistent(err) => write!(f, "inconsistent settings: {}", err),
- }
- }
-}
-
-impl Error for SettingsError {
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- match self {
- SettingsError::IO { error: err, .. } => Some(err),
- SettingsError::Format(err) => Some(err),
- _ => None
- }
- }
-}
-
-impl Default for SettingsInner {
- fn default() -> Self {
- SettingsInner {
- instances: [(String::from(constants::DEF_INSTANCE_NAME), PathBuf::from(constants::DEF_INSTANCE_NAME).into())].into_iter().collect(),
- profiles: [(String::from(constants::DEF_PROFILE_NAME), Profile::new(constants::DEF_INSTANCE_NAME))].into_iter().collect()
- }
- }
-}
-
-impl Settings {
- async fn load_inner(path: impl AsRef<Path>) -> Result<SettingsInner, SettingsError> {
- match fs::read_to_string(&path).await {
- Ok(data) => serde_json::from_str(data.as_str()).map_err(SettingsError::Format),
- Err(e) if e.kind() == ErrorKind::NotFound => Ok(SettingsInner::default()),
- Err(e) => Err(SettingsError::IO { what: "loading settings", error: e })
- }
- }
-
- fn check_consistent(mut inner: SettingsInner, path: Option<impl AsRef<Path>>) -> Result<Settings, SettingsError> {
- inner.profiles.retain(|name, profile| {
- if !inner.instances.contains_key(&profile.instance) {
- warn!("Settings inconsistency: profile {} refers to instance {}, which does not exist. Ignoring this profile.", name, profile.instance);
- false
- } else {
- true
- }
- });
-
- // there will be more checks later maybe
-
- Ok(Settings {
- path: path.map(|p| p.as_ref().to_owned()),
- inner
- })
- }
-
- pub async fn load(path: impl AsRef<Path>) -> Result<Settings, SettingsError> {
- Self::check_consistent(Self::load_inner(&path).await?, Some(path))
- }
-
- pub fn get_path(&self) -> Option<&Path> {
- self.path.as_deref()
- }
-
- pub async fn save_to(&self, path: impl AsRef<Path>) -> Result<(), SettingsError> {
- let path = path.as_ref();
-
- if let Some(parent) = path.parent() {
- fs::create_dir_all(parent).await
- .map_err(|e| SettingsError::IO { what: "saving settings (creating directory)", error: e })?;
- }
-
- let mut file = File::create(path).await
- .map_err(|e| SettingsError::IO { what: "saving settings (open)", error: e })?;
-
- file.write_all(serde_json::to_string_pretty(&self.inner).map_err(SettingsError::Format)?.as_bytes()).await
- .map_err(|e| SettingsError::IO { what: "saving settings (write)", error: e })?;
-
- Ok(())
- }
-
- pub async fn save(&self) -> Result<(), SettingsError> {
- self.save_to(self.path.as_ref().expect("save() called on Settings instance not loaded from file")).await
- }
-
- pub fn get_instance(&self, name: &str) -> Option<&Instance> {
- self.inner.instances.get(name)
- }
-
- pub fn get_profile(&self, name: &str) -> Option<&Profile> {
- self.inner.profiles.get(name)
- }
-
- pub fn get_instance_for(&self, profile: &Profile) -> &Instance {
- self.inner.instances.get(&profile.instance).unwrap()
- }
-}
-
-#[derive(Deserialize, Serialize, Debug, Clone)]
-pub struct Instance {
- path: PathBuf // relative to launcher home (or absolute)
-}
-
-#[derive(Deserialize, Serialize, Debug, Clone)]
-#[serde(rename_all = "snake_case")]
-pub enum ProfileVersion {
- LatestSnapshot,
- LatestRelease,
- #[serde(untagged)]
- Specific(String)
-}
-
-#[derive(Deserialize, Serialize, Debug, Clone, Copy)]
-pub struct Resolution {
- width: u32,
- height: u32
-}
-
-impl Default for Resolution {
- fn default() -> Self {
- Resolution { width: 864, height: 480 }
- }
-}
-
-#[derive(Deserialize, Serialize, Debug, Clone)]
-pub struct Profile {
- game_version: ProfileVersion,
- java_runtime: Option<String>,
- instance: String,
-
- #[serde(default)]
- jvm_arguments: Vec<String>,
- #[serde(default)]
- legacy_launch: bool,
-
- resolution: Option<Resolution>
-}
-
-impl<P: AsRef<Path>> From<P> for Instance {
- fn from(path: P) -> Self {
- Self { path: path.as_ref().into() }
- }
-}
-
-impl Instance {
- pub async fn get_path(&self, home: impl AsRef<Path>) -> Result<PathBuf, io::Error> {
- let path = self.path.as_path();
-
- if path.is_relative() {
- Ok([home.as_ref(), Path::new("instances"), path].iter().collect::<PathBuf>())
- } else {
- fs::canonicalize(path).await
- }
- }
-}
-
-const DEF_JVM_ARGUMENTS: [&str; 7] = [
- "-Xmx2G",
- "-XX:+UnlockExperimentalVMOptions",
- "-XX:+UseG1GC",
- "-XX:G1NewSizePercent=20",
- "-XX:G1ReservePercent=20",
- "-XX:MaxGCPauseMillis=50",
- "-XX:G1HeapRegionSize=32M"
-];
-
-impl Profile {
- fn new(instance_name: &str) -> Self {
- Self {
- game_version: ProfileVersion::LatestRelease,
- java_runtime: None,
- instance: instance_name.into(),
- jvm_arguments: DEF_JVM_ARGUMENTS.iter().map(|s| String::from(*s)).collect(),
- legacy_launch: false,
- resolution: None
- }
- }
-
- pub fn get_version(&self) -> &ProfileVersion {
- &self.game_version
- }
-
- pub fn get_instance_name(&self) -> &str {
- &self.instance
- }
-
- pub fn iter_arguments(&self) -> impl Iterator<Item = &String> {
- self.jvm_arguments.iter()
- }
-
- pub fn get_resolution(&self) -> Option<Resolution> {
- self.resolution
- }
-
- pub fn get_java_runtime(&self) -> Option<&String> {
- self.java_runtime.as_ref()
- }
-
- pub fn is_legacy_launch(&self) -> bool {
- self.legacy_launch
- }
-}