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
36mod utils;
47
5- use eframe:: egui;
6-
78fn 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
114159impl 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
125175impl 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