Skip to content
This repository was archived by the owner on Aug 13, 2025. It is now read-only.

Commit ea3d601

Browse files
committed
1 fix and 2 new features
1 parent 2cfb848 commit ea3d601

2 files changed

Lines changed: 259 additions & 37 deletions

File tree

src/main.rs

Lines changed: 114 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
use utils::{create_desktop_file, my_exe_path, get_fancy_name, reg_uri_scheme, exec_command};
1+
use std::sync::{Arc, Mutex};
2+
use std::thread;
3+
use eframe::egui;
4+
use utils::{create_desktop_file, my_exe_path, get_fancy_name, reg_uri_scheme, exec_command, launch_game};
25

36
mod utils;
47

5-
use eframe::egui;
6-
78
fn main()
89
{
10+
let resolution = utils::get_display_mode();
11+
if let Some((width, height, rate)) = resolution {
12+
println!("CoDLinux: Display resolution: {}x{} {} Hz", width, height, rate);
13+
} else {
14+
println!("CoDLinux: Unable to get display resolution.");
15+
}
16+
917
println!("CoDLinux: Looking for game executables...");
1018
let mut uo = false;
1119
let mut cod1 = false;
@@ -26,14 +34,11 @@ fn main()
2634
let exe_name = utils::get_exe_name(executable);
2735
if exe_name.to_lowercase() == "codmp.exe" {
2836
cod1 = true;
29-
}
30-
else if exe_name.to_lowercase() == "coduomp.exe" {
37+
} else if exe_name.to_lowercase() == "coduomp.exe" {
3138
uo = true;
32-
}
33-
else if exe_name.to_lowercase() == "iw1x.exe" {
39+
} else if exe_name.to_lowercase() == "iw1x.exe" {
3440
iw1x = true;
35-
}
36-
else if exe_name.to_lowercase() == "t1x.exe" {
41+
} else if exe_name.to_lowercase() == "t1x.exe" {
3742
t1x = true;
3843
}
3944
}
@@ -53,54 +58,91 @@ fn main()
5358
}
5459
}
5560

56-
let mut args:Vec<String> = std::env::args().skip(1).collect::<Vec<_>>();
61+
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
62+
let backupprefix = format!("{}/.wine", home);
63+
64+
let mut wineprefix = utils::recall_wine_prefix().unwrap_or_else(|_| {
65+
backupprefix.clone()
66+
}
67+
);
68+
if &wineprefix == "" {
69+
wineprefix = backupprefix;
70+
}
71+
72+
let mut args: Vec<String> = std::env::args().skip(1).collect::<Vec<_>>();
5773
if let Some(first_arg) = args.get(0) {
5874
if first_arg.starts_with("iw1x://") || first_arg.starts_with("t1x://") {
59-
// Parse the IP and port from the argument
6075
let _match = if first_arg.starts_with("iw1x://") { "iw1x://" } else { "t1x://" };
6176
let stripped = first_arg.trim_start_matches(_match);
6277
let parts: Vec<&str> = stripped.split(':').collect();
63-
let ip = parts.get(0).unwrap_or(&"127.0.0.1"); // Default to 127.0.0.1 if no IP is provided
64-
let port = parts.get(1).unwrap_or(&"28960"); // Default to 28960 if no port is provided
78+
let ip = parts.get(0).unwrap_or(&"127.0.0.1");
79+
let port = parts.get(1).unwrap_or(&"28960");
6580

66-
// Replace the argument with "+connect ip:port"
6781
args[0] = format!("+connect {}:{}", ip, port);
6882

6983
let args_str = args.join(" ");
7084
if iw1x {
7185
for exe in &executables {
7286
if exe.to_lowercase().contains("iw1x.exe") {
73-
exec_command(&format!("MESA_EXTENSION_MAX_YEAR=2003 force_s3tc_enable=true __GL_ExtensionStringVersion=17700 wine {} {}", exe, args_str)).unwrap();
87+
/*exec_command(&format!(
88+
"WINEPREFIX={} MESA_EXTENSION_MAX_YEAR=2003 force_s3tc_enable=true __GL_ExtensionStringVersion=17700 wine {} {}",
89+
wineprefix, exe, args_str
90+
)).unwrap();
91+
utils::restore_display_mode().unwrap();*/
92+
launch_game(&wineprefix, exe, &args_str).unwrap();
7493
launched = true;
7594
}
7695
}
7796
}
7897
if t1x {
7998
for exe in &executables {
8099
if exe.to_lowercase().contains("t1x.exe") {
81-
exec_command(&format!("MESA_EXTENSION_MAX_YEAR=2003 force_s3tc_enable=true __GL_ExtensionStringVersion=17700 wine {} {}", exe, args_str)).unwrap();
100+
/*exec_command(&format!(
101+
"MESA_EXTENSION_MAX_YEAR=2003 force_s3tc_enable=true __GL_ExtensionStringVersion=17700 wine {} {}",
102+
exe, args_str
103+
)).unwrap();
104+
utils::restore_display_mode().unwrap();*/
105+
106+
launch_game(&wineprefix, exe, &args_str).unwrap();
82107
launched = true;
83108
}
84109
}
85110
}
86111
}
87112
}
88113

114+
if !launched {
115+
let args_str = args.join(" ");
116+
let saved_game = utils::recall_game().unwrap();
117+
if &saved_game != "" {
118+
launch_game(&wineprefix, &saved_game, &args_str).unwrap();
119+
launched = true;
120+
}
121+
}
89122
if !launched {
90123
println!("CoDLinux: Launching GUI...");
91124
let args_str = args.join(" ");
92125
let options = eframe::NativeOptions {
93126
viewport: egui::ViewportBuilder::default()
94-
.with_inner_size([400.0, 120.0 + ((120.0 * executables.len() as f32) - 120.0) + 20.0]),
127+
.with_inner_size([400.0, 120.0 + ((120.0 * executables.len() as f32) - 120.0) + 40.0]),
95128
..Default::default()
96129
};
130+
131+
// Create a shared thread handle
132+
let game_thread = Arc::new(Mutex::new(None::<thread::JoinHandle<()>>));
133+
let app = CoDLinuxApp::new(executables.clone(), args_str.clone(), uo, game_thread.clone(), wineprefix.clone());
134+
97135
eframe::run_native(
98136
"CoDLinux",
99137
options,
100-
Box::new(|_cc| {
101-
Ok(Box::new(CoDLinuxApp::new(executables, args_str, uo)))
102-
}),
138+
Box::new(|_cc| Ok(Box::new(app))),
103139
).unwrap();
140+
141+
// Join the game thread after GUI closes
142+
if let Some(handle) = game_thread.lock().unwrap().take() {
143+
handle.join().unwrap();
144+
}
145+
println!("CoDLinux: GUI closed.");
104146
}
105147
}
106148

@@ -109,58 +151,94 @@ pub struct CoDLinuxApp
109151
executables: Vec<String>,
110152
args: String,
111153
uo: bool,
154+
game_thread: Arc<Mutex<Option<thread::JoinHandle<()>>>>,
155+
remember: bool,
156+
wine_prefix: String,
112157
}
113158

114159
impl CoDLinuxApp
115160
{
116-
fn new(executables: Vec<String>, args: String, uo: bool) -> Self {
161+
fn new(executables: Vec<String>, args: String, uo: bool, game_thread: Arc<Mutex<Option<thread::JoinHandle<()>>>>, wine_prefix: String) -> Self {
162+
println!("CoDLinux: Creating app...");
163+
println!("CoDLinux: Prefix: {:?}", wine_prefix);
117164
CoDLinuxApp {
118165
executables,
119166
args,
120167
uo,
168+
game_thread,
169+
remember: false,
170+
wine_prefix,
121171
}
122172
}
123173
}
124174

125175
impl eframe::App for CoDLinuxApp
126176
{
127177
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
178+
let mut visuals = egui::Visuals::default();
179+
visuals.text_cursor = egui::style::TextCursorStyle {
180+
stroke: egui::Stroke::new(2.0, egui::Color32::from_rgb(187, 220, 61)), // Red cursor
181+
preview: true,
182+
blink: true,
183+
on_duration: 0.5,
184+
off_duration: 0.5,
185+
};
186+
ctx.set_visuals(visuals);
187+
128188
let mut style = (*ctx.style()).clone();
129189
style.visuals.widgets.hovered.bg_stroke.color = egui::Color32::from_rgb(180, 127, 240);
130190
style.visuals.widgets.active.bg_stroke.color = egui::Color32::from_rgb(187, 220, 61);
191+
style.visuals.widgets.open.bg_stroke.color = egui::Color32::from_rgb(187, 220, 61);
131192
style.visuals.widgets.hovered.bg_stroke.width = 1.5;
132193
style.visuals.widgets.active.bg_stroke.width = 2.0;
133194
ctx.set_style(style);
134195

135196
egui::CentralPanel::default().show(ctx, |ui| {
197+
ui.visuals_mut().selection.stroke = egui::Stroke::new(1.5, egui::Color32::from_rgb(187, 220, 61));
136198
ui.vertical_centered(|ui| {
137199
ui.heading("Choose a Game");
138200
for executable in &self.executables {
139201
let game_name = get_fancy_name(executable, &self.uo);
140202

141-
let text = egui::RichText::new(game_name).size(24.0).strong();
203+
let text = egui::RichText::new(&game_name).size(24.0).strong();
142204
let button = egui::Button::new(text).min_size(egui::vec2(300.0, 100.0));
143205

144206
if ui.add(button).clicked() {
145-
146-
// Run the command in a separate thread
147-
let executable_clone = executable.clone();
148-
let args_clone = self.args.clone();
149-
std::thread::spawn(move || {
150-
let command = format!(
151-
"MESA_EXTENSION_MAX_YEAR=2003 force_s3tc_enable=true __GL_ExtensionStringVersion=17700 wine {} {}",
152-
executable_clone, args_clone
153-
);
154-
if let Err(e) = exec_command(&command) {
155-
eprintln!("Failed to execute command: {}", e);
207+
if self.remember {
208+
println!("CoDLinux: Remembering choice for {}, path: {}", &game_name, &executable);
209+
let _ = utils::remember_game(&executable);
210+
}
211+
let exe = executable.clone();
212+
let args = self.args.clone();
213+
214+
let wine_prefix = self.wine_prefix.clone();
215+
let game_handle = thread::spawn(move || {
216+
//let _ = utils::save_wine_prefix(&wine_prefix);
217+
let rrr = utils::save_wine_prefix(&wine_prefix);
218+
if rrr.is_err() {
219+
println!("CoDLinux: Error saving wine prefix: {}", rrr.unwrap_err());
156220
}
221+
println!("CoDLinux: prefix: {}", &wine_prefix);
222+
let _ = launch_game(&wine_prefix, &exe, &args);
157223
});
158224

159-
// close the GUI
160-
std::process::exit(0);
225+
*self.game_thread.lock().unwrap() = Some(game_handle);
226+
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
227+
}
228+
}
229+
230+
ui.checkbox(&mut self.remember, "Remember my choice");
231+
let text_edit = ui.add(egui::TextEdit::singleline(&mut self.wine_prefix)
232+
.hint_text("Wine Prefix")
233+
.desired_width(200.0));
234+
235+
if text_edit.changed() {
236+
if let Ok(new_prefix) = std::fs::canonicalize(&self.wine_prefix) {
237+
self.wine_prefix = new_prefix.to_string_lossy().to_string();
238+
println!("CoDLinux: New Wine Prefix: {}", self.wine_prefix);
161239
}
162240
}
163241
});
164242
});
165243
}
166-
}
244+
}

0 commit comments

Comments
 (0)