@@ -16,6 +16,8 @@ pub struct ModBlacklist {
1616pub struct ModBlacklistProfile {
1717 pub name : String ,
1818 pub mods : Vec < ModBlacklist > ,
19+ #[ serde( default ) ]
20+ pub mod_options_order : Vec < String > ,
1921}
2022
2123pub fn apply_mod_blacklist_profile (
@@ -47,6 +49,49 @@ pub fn apply_mod_blacklist_profile(
4749 . join ( "\n " ) ) ,
4850 ) ?;
4951
52+ write_mod_options_order ( game_path, & profile. mod_options_order ) ?;
53+
54+ Ok ( ( ) )
55+ }
56+
57+ /// Write modoptionsorder.txt from the given ordered file list.
58+ fn write_mod_options_order ( game_path : & String , order : & [ String ] ) -> anyhow:: Result < ( ) > {
59+ let path = Path :: new ( game_path) . join ( "Mods" ) . join ( "modoptionsorder.txt" ) ;
60+ if order. is_empty ( ) {
61+ // If no order specified, remove the file so Everest uses alphabetical order
62+ if path. exists ( ) {
63+ fs:: remove_file ( & path) ?;
64+ }
65+ return Ok ( ( ) ) ;
66+ }
67+ let content = format ! (
68+ "# Mod Options order\n # This file is generated by CeleMod\n \n {}\n " ,
69+ order. join( "\n " )
70+ ) ;
71+ fs:: write ( path, content) ?;
72+ Ok ( ( ) )
73+ }
74+
75+ /// Update the mod_options_order in a profile and immediately apply it to modoptionsorder.txt.
76+ pub fn set_mod_options_order (
77+ game_path : & String ,
78+ profile_name : & String ,
79+ order : Vec < String > ,
80+ ) -> anyhow:: Result < ( ) > {
81+ let mut profile = get_mod_blacklist_profiles ( game_path)
82+ . into_iter ( )
83+ . find ( |v| & v. name == profile_name)
84+ . context ( "Profile not found" ) ?;
85+
86+ profile. mod_options_order = order;
87+
88+ let profile_path = Path :: new ( game_path)
89+ . join ( "celemod_blacklist_profiles" )
90+ . join ( format ! ( "{}.json" , profile_name) ) ;
91+ fs:: write ( & profile_path, serde_json:: to_string_pretty ( & profile) . unwrap ( ) ) ?;
92+
93+ write_mod_options_order ( game_path, & profile. mod_options_order ) ?;
94+
5095 Ok ( ( ) )
5196}
5297
@@ -110,6 +155,7 @@ pub fn get_mod_blacklist_profiles(game_path: &String) -> Vec<ModBlacklistProfile
110155 }
111156 } )
112157 . collect ( ) ,
158+ mod_options_order : vec ! [ ] ,
113159 } ;
114160
115161 fs:: write (
@@ -127,6 +173,7 @@ pub fn get_mod_blacklist_profiles(game_path: &String) -> Vec<ModBlacklistProfile
127173 let profile = ModBlacklistProfile {
128174 name : "Default" . to_string ( ) ,
129175 mods : vec ! [ ] ,
176+ mod_options_order : vec ! [ ] ,
130177 } ;
131178 let blacklist_path = Path :: new ( game_path) . join ( "celemod_blacklist_profiles" ) ;
132179 fs:: create_dir_all ( & blacklist_path) . unwrap ( ) ;
@@ -193,6 +240,7 @@ pub fn new_mod_blacklist_profile(game_path: &String, profile_name: &String) -> a
193240 serde_json:: to_string_pretty ( & ModBlacklistProfile {
194241 name : profile_name. clone ( ) ,
195242 mods : vec ! [ ] ,
243+ mod_options_order : vec ! [ ] ,
196244 } )
197245 . unwrap ( ) ,
198246 ) ?;
@@ -232,6 +280,12 @@ pub fn sync_blacklist_profile_from_file(
232280 }
233281 let data = fs:: read_to_string ( blacklist) ?;
234282 let mods = get_installed_mods_sync ( game_path. clone ( ) + "/Mods" ) ;
283+ // Preserve existing mod_options_order if profile already exists
284+ let existing_order = get_mod_blacklist_profiles ( game_path)
285+ . into_iter ( )
286+ . find ( |v| & v. name == profile_name)
287+ . map ( |v| v. mod_options_order )
288+ . unwrap_or_default ( ) ;
235289 let profile = ModBlacklistProfile {
236290 name : profile_name. clone ( ) ,
237291 mods : data
@@ -249,6 +303,7 @@ pub fn sync_blacklist_profile_from_file(
249303 file : v. to_string ( ) ,
250304 } )
251305 . collect ( ) ,
306+ mod_options_order : existing_order,
252307 } ;
253308 let blacklist_path = Path :: new ( game_path)
254309 . join ( "celemod_blacklist_profiles" )
0 commit comments