aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src-tauri/src/core/rules.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src-tauri/src/core/rules.rs')
-rw-r--r--src-tauri/src/core/rules.rs88
1 files changed, 75 insertions, 13 deletions
diff --git a/src-tauri/src/core/rules.rs b/src-tauri/src/core/rules.rs
index 71abda5..781515a 100644
--- a/src-tauri/src/core/rules.rs
+++ b/src-tauri/src/core/rules.rs
@@ -1,7 +1,8 @@
+use crate::core::config::FeatureFlags;
use crate::core::game_version::Rule;
use std::env;
-pub fn is_library_allowed(rules: &Option<Vec<Rule>>) -> bool {
+pub fn is_library_allowed(rules: &Option<Vec<Rule>>, features: Option<&FeatureFlags>) -> bool {
// If no rules, it's allowed by default
let Some(rules) = rules else {
return true;
@@ -39,36 +40,97 @@ pub fn is_library_allowed(rules: &Option<Vec<Rule>>) -> bool {
let mut allowed = false;
for rule in rules {
- if rule_matches(rule) {
+ if rule_matches(rule, features) {
allowed = rule.action == "allow";
}
}
allowed
}
-fn rule_matches(rule: &Rule) -> bool {
- // Feature-based rules (e.g., is_demo_user, has_quick_plays_support, is_quick_play_singleplayer)
- // are not implemented in this launcher, so we return false for any rule that has features.
- // This prevents adding arguments like --demo, --quickPlayPath, --quickPlaySingleplayer, etc.
- if rule.features.is_some() {
- return false;
+fn rule_matches(rule: &Rule, features: Option<&FeatureFlags>) -> bool {
+ // Feature-based rules: apply only if all listed features evaluate to true
+ if let Some(f) = &rule.features {
+ if let Some(map) = f.as_object() {
+ // If no feature flags provided, we cannot satisfy feature rules
+ let ctx = match features {
+ Some(ff) => ff,
+ None => return false,
+ };
+
+ for (key, val) in map.iter() {
+ let required = val.as_bool().unwrap_or(false);
+ // Map known features
+ let actual = match key.as_str() {
+ "is_demo_user" => ctx.demo_user,
+ "has_quick_plays_support" => ctx.quick_play_enabled,
+ "is_quick_play_singleplayer" => {
+ ctx.quick_play_enabled && ctx.quick_play_singleplayer
+ }
+ "is_quick_play_multiplayer" => {
+ ctx.quick_play_enabled
+ && ctx
+ .quick_play_multiplayer_server
+ .as_ref()
+ .map(|s| !s.is_empty())
+ .unwrap_or(false)
+ }
+ _ => false,
+ };
+ if required && !actual {
+ return false;
+ }
+ if !required && actual {
+ // If rule specifies feature must be false, but it's true, do not match
+ return false;
+ }
+ }
+ } else {
+ // Malformed features object
+ return false;
+ }
}
match &rule.os {
None => true, // No OS condition means it applies to all
Some(os_rule) => {
+ // Check OS name
if let Some(os_name) = &os_rule.name {
- match os_name.as_str() {
+ let os_match = match os_name.as_str() {
"osx" | "macos" => env::consts::OS == "macos",
"linux" => env::consts::OS == "linux",
"windows" => env::consts::OS == "windows",
_ => false, // Unknown OS name in rule
+ };
+
+ if !os_match {
+ return false;
}
- } else {
- // OS rule exists but name is None? Maybe checking version/arch only.
- // For simplicity, mostly name is used.
- true
}
+
+ // Check architecture if specified
+ if let Some(arch) = &os_rule.arch {
+ let current_arch = env::consts::ARCH;
+ // Strict match: only exact architecture or known compatibility mapping
+ let compatible = match (arch.as_str(), current_arch) {
+ ("x86_64", "x86_64") => true,
+ ("x86", "x86") => true,
+ ("aarch64", "aarch64") => true,
+ // Treat "x86" not as matching x86_64 (be strict)
+ _ => arch == current_arch,
+ };
+ if !compatible {
+ return false;
+ }
+ }
+
+ // Check version if specified (for OS version compatibility)
+ if let Some(_version) = &os_rule.version {
+ // Version checking would require parsing OS version strings
+ // For now, we accept all versions (conservative approach)
+ // In the future, parse version and compare
+ }
+
+ true
}
}
}