diff options
Diffstat (limited to 'src/launcher/runner.rs')
| -rw-r--r-- | src/launcher/runner.rs | 105 |
1 files changed, 88 insertions, 17 deletions
diff --git a/src/launcher/runner.rs b/src/launcher/runner.rs index 8d12197..4d07f20 100644 --- a/src/launcher/runner.rs +++ b/src/launcher/runner.rs @@ -1,27 +1,34 @@ use std::borrow::Cow; -use crate::launcher::Launch; -use crate::launcher::strsub::SubFunc; +use std::ffi::OsString; +use std::iter; +use crate::version::{CompleteVersion, FeatureMatcher}; +use super::rules::CompatCheck; +use super::strsub::{self, SubFunc}; +use super::LaunchInfo; -impl<'k, 'rep, 'l: 'rep> SubFunc<'k, 'rep> for &'rep Launch<'l> { - fn substitute(self, key: &'k str) -> Option<Cow<'rep, str>> { +#[derive(Clone, Copy)] +struct LaunchArgSub<'a: 'l, 'l, F: FeatureMatcher>(&'a LaunchInfo<'l, F>); + +impl<'rep, 'l, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, 'l, F> { + fn substitute(&self, key: &str) -> Option<Cow<'rep, str>> { match key { - "assets_index_name" => self.asset_index_name.as_ref().map(|s| Cow::Borrowed(s.as_str())), - "assets_root" => Some(self.launcher.assets.get_home().to_string_lossy()), + "assets_index_name" => self.0.asset_index_name.as_ref().map(|s| Cow::Borrowed(s.as_str())), + "assets_root" => Some(self.0.launcher.assets.get_home().to_string_lossy()), "auth_access_token" => Some(Cow::Borrowed("-")), // TODO "auth_player_name" => Some(Cow::Borrowed("Player")), // TODO "auth_session" => Some(Cow::Borrowed("-")), // TODO "auth_uuid" => Some(Cow::Borrowed("00000000-0000-0000-0000-000000000000")), // TODO "auth_xuid" => Some(Cow::Borrowed("00000000-0000-0000-0000-000000000000")), // TODO - "classpath" => Some(Cow::Borrowed(self.classpath.as_str())), // TODO + "classpath" => Some(Cow::Borrowed(self.0.classpath.as_str())), // TODO "classpath_separator" => None, // FIXME - "game_assets" => self.virtual_assets_path.as_ref().map(|s| s.to_string_lossy()), - "game_directory" => Some(self.instance_home.to_string_lossy()), + "game_assets" => self.0.virtual_assets_path.as_ref().map(|s| s.to_string_lossy()), + "game_directory" => Some(self.0.instance_home.to_string_lossy()), "language" => Some(Cow::Borrowed("en-us")), // ??? "launcher_name" => Some(Cow::Borrowed("ozone (olauncher 3)")), // TODO "launcher_version" => Some(Cow::Borrowed("yeah")), // TODO - "library_directory" => Some(self.launcher.libraries.home.to_string_lossy()), - "natives_directory" => Some(self.natives_path.to_string_lossy()), - "primary_jar" => self.client_jar.as_ref().map(|p| p.to_string_lossy()), + "library_directory" => Some(self.0.launcher.libraries.home.to_string_lossy()), + "natives_directory" => Some(self.0.natives_path.to_string_lossy()), + "primary_jar" => self.0.client_jar.as_ref().map(|p| p.to_string_lossy()), "quickPlayMultiplayer" => None, // TODO "quickPlayPath" => None, // TODO "quickPlayRealms" => None, // TODO @@ -31,17 +38,81 @@ impl<'k, 'rep, 'l: 'rep> SubFunc<'k, 'rep> for &'rep Launch<'l> { "user_properties" => Some(Cow::Borrowed("{}")), // TODO "user_property_map" => Some(Cow::Borrowed("[]")), // TODO "user_type" => Some(Cow::Borrowed("legacy")), // TODO - "version_name" => Some(Cow::Borrowed(&self.version_id.as_ref())), - "version_type" => self.version_type.as_ref().map(|s| Cow::Borrowed(s.to_str())), + "version_name" => Some(Cow::Borrowed(&self.0.version_id.as_ref())), + "version_type" => self.0.version_type.as_ref().map(|s| Cow::Borrowed(s.to_str())), _ => { if let Some(asset_key) = key.strip_prefix("asset=") { - return self.asset_index.as_ref() + return self.0.asset_index.as_ref() .map_or(None, |idx| idx.objects.get(asset_key)) - .map(|obj| Cow::Owned(self.launcher.assets.get_object_path(obj).to_string_lossy().into_owned())) + .map(|obj| Cow::Owned(self.0.launcher.assets.get_object_path(obj).to_string_lossy().into_owned())) } None } } } -}
\ No newline at end of file +} + +#[derive(Clone, Copy)] +pub enum ArgumentType { + JVM, + Game +} + +struct OptionalIterator<I> +where + I: Iterator +{ + opt: Option<I> +} + +impl<I: Iterator> Iterator for OptionalIterator<I> { + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + match self.opt { + Some(ref mut i) => i.next(), + None => None + } + } +} + +impl<II: IntoIterator> From<Option<II>> for OptionalIterator<II::IntoIter> { + fn from(opt: Option<II>) -> Self { + OptionalIterator { + opt: opt.map(IntoIterator::into_iter) + } + } +} + +pub fn build_arguments<'l, F: FeatureMatcher>(launch: &LaunchInfo<'l, F>, version: &CompleteVersion, arg_type: ArgumentType) -> Vec<OsString> { + let sub = LaunchArgSub(launch); + let system_info = &launch.launcher.system_info; + + if let Some(arguments) = version.arguments.as_ref().map_or(None, |args| match arg_type { + ArgumentType::JVM => args.jvm.as_ref(), + ArgumentType::Game => args.game.as_ref() + }) { + arguments.iter() + .flat_map(|wa| OptionalIterator::from(wa.rules_apply(system_info, launch.feature_matcher).ok().map(|_| &wa.value))) + .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned())).collect() + } else if let Some(arguments) = version.minecraft_arguments.as_ref() { + match arg_type { + ArgumentType::JVM => { + todo!() + } + ArgumentType::Game => { + arguments.split(' ') + .chain(iter::once("--demo") + .take_while(|_| launch.feature_matcher.matches("is_demo_user"))) + .chain(iter::once(["--width", "${resolution_width}", "--height", "${resolution_height}"]) + .take_while(|_| launch.feature_matcher.matches("has_custom_resolution")) + .flatten()) + .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned())) + .collect() + } + } + } else { + Vec::default() + } +} |
