Skip to content

Commit 1a60606

Browse files
committed
CLI version
1 parent 2cf28be commit 1a60606

File tree

9 files changed

+282
-51
lines changed

9 files changed

+282
-51
lines changed

Cargo.lock

Lines changed: 113 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ readme = "README.md"
1010
keywords = ["starcraft", "multi", "launcher", "rust", "windows"]
1111
categories = ["game", "utility", "windows"]
1212

13+
[lib]
14+
name = "sclauncher"
15+
path = "src/lib.rs"
16+
17+
[[bin]]
18+
name = "sclauncher-cli"
19+
path = "src/bin/cli.rs"
20+
21+
[[bin]]
22+
name = "sclauncher-gui"
23+
path = "src/bin/gui.rs"
24+
1325
[dependencies]
1426
windows = { version = "0.56.0", features = [
1527
"Wdk_Foundation",
@@ -31,7 +43,19 @@ windows = { version = "0.56.0", features = [
3143
winreg = "0.52.0"
3244
tokio = { version = "1", features = ["full"] }
3345
regex = "1.10.4"
46+
clap = { version = "4.5.4", features = ["derive"] }
3447
# windows-targets = "0.52.5"
3548

3649
[build-dependencies]
3750
embed-resource = "2.4"
51+
52+
[profile.release]
53+
opt-level = 3
54+
debug = false
55+
rpath = false
56+
lto = true
57+
debug-assertions = false
58+
codegen-units = 1
59+
panic = 'unwind'
60+
incremental = false
61+
overflow-checks = false

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@ I created this as a practice project to gain familiarity with `windows-rs` by po
2222

2323
The original C++ version can be found at [sc_multiloader](https://github.com/somersby10ml/sc_multiloader/tree/main) by @somerby10ml
2424

25+
## Play
26+
27+
### CLI
28+
29+
If you want to run N games, use `-n`.
30+
31+
```powershell
32+
./sclauncher-cli.exe -n 3
33+
```
34+
35+
Want to run 64bits? pass `-i`
36+
37+
```powershell
38+
./sclauncher-cli.exe -n 3 -i
39+
```
40+
41+
### GUI
42+
2543
## Key Features
2644

2745
### Process Management
@@ -62,6 +80,7 @@ Uses Rust's async capabilities and safe concurrency models to manage multiple ga
6280
## TODO
6381

6482
- [ ] leptos GUI
83+
- [x] clap CLI
6584
- [x] Process get
6685
- [x] Process handle information
6786
- [x] Kill process's handle

sc-multi-launcher.exe

-1.12 MB
Binary file not shown.

sclauncher-cli.exe

764 KB
Binary file not shown.

src/bin/cli.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
use std::{io::Write, path::PathBuf};
2+
3+
use sclauncher::util::{
4+
admin::{is_admin, run_as_admin},
5+
game::GameManager,
6+
reg::{async_registry_search, get_game_path},
7+
};
8+
9+
use clap::Parser;
10+
use winreg::enums::HKEY_LOCAL_MACHINE;
11+
12+
use std::io;
13+
14+
use tokio::time::{sleep, Duration};
15+
16+
#[derive(Parser, Debug)]
17+
#[command(
18+
name = "SC1 Mutli Loader",
19+
version = "1.0",
20+
author = "Seok Won Choi",
21+
about = "StarCraft 1 Multi launcher"
22+
)]
23+
struct Args {
24+
/// Performs an asynchronous search in the registry
25+
#[arg(short, long, action = clap::ArgAction::SetTrue)]
26+
async_registry_search: bool,
27+
28+
/// Number of times to launch the game
29+
#[arg(short, long, default_value_t = 2)]
30+
num_launches: u32,
31+
32+
/// 64bits or 32bits
33+
#[arg(short, long, default_value_t = false)]
34+
is_64bit: bool,
35+
}
36+
37+
#[tokio::main]
38+
async fn main() {
39+
if !is_admin() {
40+
println!("Not running as admin. Attempting to elevate...");
41+
if run_as_admin() {
42+
println!("Please restart the application with admin privileges.");
43+
return; // Exit the current instance
44+
} else {
45+
println!("Failed to elevate privileges.");
46+
return;
47+
}
48+
}
49+
50+
let args = Args::parse();
51+
let game_manager = GameManager::new();
52+
53+
// Try to get game path from user input or registry if not found initially
54+
let game_path = match get_game_path_or_search(&args).await {
55+
Ok(path) => path,
56+
Err(e) => {
57+
eprintln!("{}", e);
58+
return;
59+
}
60+
};
61+
62+
// Launch the game the specified number of times
63+
launch_game_multiple_times(&game_manager, &game_path, args.num_launches).await;
64+
65+
println!("Press Enter to kill all games...");
66+
let mut pause = String::new();
67+
std::io::stdin().read_line(&mut pause).unwrap();
68+
69+
game_manager.kill_all_games().await;
70+
}
71+
72+
async fn get_game_path_or_search(args: &Args) -> Result<PathBuf, String> {
73+
// Try to get the game path directly
74+
let direct_path = get_game_path(args.is_64bit);
75+
76+
if args.async_registry_search || direct_path.is_none() {
77+
println!("Attempting to locate StarCraft.exe...");
78+
79+
// Perform the registry search if direct path is not found or if async search is requested
80+
let matches =
81+
async_registry_search(HKEY_LOCAL_MACHINE, "StarCraft", "InstallLocation").await;
82+
if matches.is_empty() && direct_path.is_none() {
83+
// If no matches and no direct path, prompt user for manual input
84+
return prompt_user_for_path();
85+
}
86+
87+
// Use the first found path from registry search if available
88+
matches.first().map_or_else(
89+
|| direct_path.ok_or_else(|| "StarCraft not found.".to_string()), // Use direct path if no registry matches
90+
|(_, path)| Ok(PathBuf::from(path)), // Convert the registry path to PathBuf
91+
)
92+
} else {
93+
// If direct path is found, return it
94+
direct_path.ok_or_else(|| "StarCraft not found.".to_string())
95+
}
96+
}
97+
98+
fn prompt_user_for_path() -> Result<PathBuf, String> {
99+
println!("Please enter the full path to StarCraft.exe:");
100+
let mut path_input = String::new();
101+
io::stdout().flush().expect("Failed to flush stdout");
102+
io::stdin()
103+
.read_line(&mut path_input)
104+
.map_err(|e| e.to_string())?;
105+
106+
let trimmed_path = path_input.trim();
107+
if trimmed_path.is_empty() {
108+
return Err("No path provided.".to_string());
109+
}
110+
111+
let path = PathBuf::from(trimmed_path);
112+
if !path.exists() {
113+
return Err("The provided path does not exist.".to_string());
114+
}
115+
Ok(path)
116+
}
117+
118+
async fn launch_game_multiple_times(game_manager: &GameManager, path: &PathBuf, num_launches: u32) {
119+
for i in 0..num_launches {
120+
println!("Launching StarCraft.exe [{}]", i + 1);
121+
game_manager.launch_game(path.to_path_buf()).await;
122+
sleep(Duration::from_secs(1)).await;
123+
}
124+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod util;

0 commit comments

Comments
 (0)