zeroed-some/wanda / a105512

Browse files

launch --standalone uses game prefix for shared wineserver

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
a105512e3264b401174c76676ccf06f07f8546bb
Parents
cc84d9b
Tree
29fa745

1 changed file

StatusFile+-
M crates/wanda-cli/src/commands/launch.rs 100 8
crates/wanda-cli/src/commands/launch.rsmodified
@@ -31,6 +31,14 @@ pub struct LaunchArgs {
3131
     /// Wait for the game to exit
3232
     #[arg(long, short)]
3333
     wait: bool,
34
+
35
+    /// Standalone mode: launch WeMod only, start the game from WeMod's UI
36
+    #[arg(long)]
37
+    standalone: bool,
38
+
39
+    /// Specify Proton version to use (overrides config)
40
+    #[arg(long)]
41
+    proton: Option<String>,
3442
 }
3543
 
3644
 pub async fn run(args: LaunchArgs, config_path: Option<PathBuf>) -> Result<()> {
@@ -90,18 +98,92 @@ pub async fn run(args: LaunchArgs, config_path: Option<PathBuf>) -> Result<()> {
9098
             return Err(WandaError::WemodNotInstalled);
9199
         }
92100
 
101
+        // In standalone mode, use the GAME's compat data prefix instead
102
+        // of wanda's prefix. This ensures WeMod and the game share the
103
+        // same wineserver. WeMod's files are symlinked from wanda's
104
+        // prefix into the game's prefix.
105
+        let game_prefix;
106
+        let launch_prefix = if args.standalone {
107
+            let compat_data = game.compat_data_path.as_ref().ok_or_else(|| {
108
+                WandaError::LaunchFailed {
109
+                    reason: format!(
110
+                        "Game '{}' has no Proton compat data. Has it been launched with Proton before?",
111
+                        game.name
112
+                    ),
113
+                }
114
+            })?;
115
+
116
+            println!(
117
+                "  Using game prefix: {}",
118
+                style(compat_data.display()).dim()
119
+            );
120
+
121
+            // Symlink WeMod into the game's prefix
122
+            let wemod_src = prefix.wemod_path();
123
+            let target_local = compat_data.join("pfx/drive_c/users/steamuser/AppData/Local");
124
+            let _ = std::fs::create_dir_all(&target_local);
125
+            let wemod_dir_name = wemod_src.file_name().unwrap_or_default();
126
+            let link_path = target_local.join(wemod_dir_name);
127
+            if !link_path.exists() {
128
+                let _ = std::os::unix::fs::symlink(&wemod_src, &link_path);
129
+            }
130
+
131
+            // Symlink WeMod roaming data
132
+            let roaming_src = prefix.path.join("pfx/drive_c/users/steamuser/AppData/Roaming/WeMod");
133
+            if roaming_src.exists() {
134
+                let target_roaming = compat_data.join("pfx/drive_c/users/steamuser/AppData/Roaming");
135
+                let _ = std::fs::create_dir_all(&target_roaming);
136
+                let roaming_link = target_roaming.join("WeMod");
137
+                if !roaming_link.exists() {
138
+                    let _ = std::os::unix::fs::symlink(&roaming_src, &roaming_link);
139
+                }
140
+            }
141
+
142
+            // Patch mscorlib in the game's prefix
143
+            // (done by the launcher's setup_steam_library, but mscorlib
144
+            // needs manual patching here)
145
+
146
+            // Create a WandaPrefix pointing to the game's compat data
147
+            game_prefix = wanda_core::prefix::WandaPrefix {
148
+                name: "game".to_string(),
149
+                path: compat_data.clone(),
150
+                wemod_installed: true,
151
+                wemod_version: prefix.wemod_version.clone(),
152
+                proton_version: prefix.proton_version.clone(),
153
+                created_at: None,
154
+                last_used: None,
155
+            };
156
+            &game_prefix
157
+        } else {
158
+            prefix
159
+        };
160
+
93161
         // Get Proton version
94162
         let proton_manager = ProtonManager::discover(&steam, &config)?;
95
-        let proton = proton_manager.get_preferred(&config)?;
163
+        let proton = if let Some(ref name) = args.proton {
164
+            proton_manager.find_by_name(name).ok_or_else(|| {
165
+                eprintln!("Available Proton versions:");
166
+                for v in &proton_manager.versions {
167
+                    eprintln!("  - {} ({})", v.name, v.compatibility);
168
+                }
169
+                WandaError::LaunchFailed {
170
+                    reason: format!("Proton version '{}' not found", name),
171
+                }
172
+            })?
173
+        } else {
174
+            proton_manager.get_preferred(&config)?
175
+        };
96176
 
97177
         println!("  Using WeMod with {}", proton.name);
98178
 
99179
         // Create launcher
100
-        let launcher = GameLauncher::new(&steam, prefix, proton);
180
+        let launcher = GameLauncher::new(&steam, launch_prefix, proton);
101181
 
182
+        let standalone = args.standalone;
102183
         let launch_config = LaunchConfig {
103184
             app_id: game.app_id,
104185
             with_wemod: true,
186
+            standalone,
105187
             wemod_delay: args.delay,
106188
             extra_args: args
107189
                 .args
@@ -112,12 +194,22 @@ pub async fn run(args: LaunchArgs, config_path: Option<PathBuf>) -> Result<()> {
112194
 
113195
         let mut handle = launcher.launch(launch_config).await?;
114196
 
115
-        println!(
116
-            "\n{} Game launched with WeMod!",
117
-            style("SUCCESS").green().bold()
118
-        );
119
-        println!("\nWeMod should appear in a separate window.");
120
-        println!("Select your game in WeMod and click Play to activate trainers.\n");
197
+        if standalone {
198
+            println!(
199
+                "\n{} WeMod launched in standalone mode!",
200
+                style("SUCCESS").green().bold()
201
+            );
202
+            println!("\nWeMod is running in the game's prefix.");
203
+            println!("Find your game in WeMod and click Play.");
204
+            println!("WeMod will launch the game directly.\n");
205
+        } else {
206
+            println!(
207
+                "\n{} Game launched with WeMod!",
208
+                style("SUCCESS").green().bold()
209
+            );
210
+            println!("\nWeMod should appear in a separate window.");
211
+            println!("Select your game in WeMod and click Play to activate trainers.\n");
212
+        }
121213
 
122214
         if args.wait {
123215
             println!("Waiting for session to end...");