rpfm_server/state/
dependencies.rs1use std::path::Path;
14
15use anyhow::{anyhow, Result};
16
17use rpfm_extensions::dependencies::Dependencies;
18
19use rpfm_ipc::helpers::DependenciesInfo;
20use rpfm_ipc::settings_keys::SECONDARY_PATH;
21
22use rpfm_lib::compression::CompressionFormat;
23
24use rpfm_telemetry::info;
25
26use rpfm_ipc::settings::{dependencies_cache_path, Settings};
27
28use super::{SessionState, load_schema, loaded_schema, parent_pack_names};
29
30impl SessionState {
31
32 pub fn set_game_selected(&mut self, game_key: &str, rebuild_dependencies: bool, settings: &Settings, disable_uuid_regeneration: bool) -> Result<(CompressionFormat, Option<DependenciesInfo>)> {
47 info!("Setting game selected.");
48 let game_changed = self.game.key() != game_key || !self.first_game_change_done;
49 self.game = self.supported_games.game(game_key)
50 .ok_or_else(|| anyhow!("The selected game is not supported!"))?
51 .clone();
52
53 for pack in self.packs.values_mut() {
55 let current_cf = pack.compression_format();
56 if current_cf != CompressionFormat::None && !self.game.compression_formats_supported().contains(¤t_cf) {
57 let new_cf = self.game.compression_formats_supported().first().copied().unwrap_or(CompressionFormat::None);
58 pack.set_compression_format(new_cf, &self.game);
59 }
60 }
61
62 load_schema(&mut self.schema, &mut self.packs, &self.game, disable_uuid_regeneration);
63
64 let dependencies_info = if rebuild_dependencies {
65 let cache_path = dependencies_cache_path()?.join(self.game.dependencies_cache_file_name());
66 let cache_path = if game_changed { Some(&*cache_path) } else { None };
67
68 let _ = self.load_dependencies(cache_path, false, settings);
70
71 Some(DependenciesInfo::new(&self.dependencies, self.game.vanilla_db_table_name_logic()))
72 } else {
73 None
74 };
75
76 let compression_format = self.packs.values().next()
77 .map(|pack| pack.compression_format())
78 .unwrap_or(CompressionFormat::None);
79
80 let game_version_number = self.game.game_version_number(&settings.path_buf(self.game.key()));
82 for pack in self.packs.values_mut() {
83 if !pack.disk_file_path().is_empty() {
84 let pfh_file_type = *pack.header().pfh_file_type();
85 pack.header_mut().set_pfh_version(self.game.pfh_version_by_file_type(pfh_file_type));
86
87 if let Some(version_number) = game_version_number {
88 pack.set_game_version(version_number);
89 }
90 }
91 }
92
93 self.first_game_change_done = true;
94 info!("Switching game selected done.");
95
96 Ok((compression_format, dependencies_info))
97 }
98
99 pub fn decode_dependency_tables(&mut self) {
101 self.dependencies.decode_tables(&self.schema);
102 }
103
104 pub fn generate_dependencies_cache(&mut self, settings: &Settings, ignore_game_files_in_ak: bool) -> Result<DependenciesInfo> {
115 let game_path = settings.path_buf(self.game.key());
116 if !game_path.is_dir() {
117 return Err(anyhow!("Game Path not configured. Go to <i>'PackFile/Settings'</i> and configure it."));
118 }
119
120 let asskit_path = settings.assembly_kit_path(&self.game).ok();
121 let mut cache = Dependencies::generate_dependencies_cache(&self.schema, &self.game, &game_path, &asskit_path, ignore_game_files_in_ak)?;
122
123 let cache_path = dependencies_cache_path()?.join(self.game.dependencies_cache_file_name());
124 cache.save(&cache_path)?;
125
126 let _ = self.load_dependencies(Some(&cache_path), true, settings);
127 Ok(DependenciesInfo::new(&self.dependencies, self.game.vanilla_db_table_name_logic()))
128 }
129
130 pub fn rebuild_dependencies(&mut self, only_parent_packs: bool, settings: &Settings) -> Result<DependenciesInfo> {
141 loaded_schema(&self.schema)?;
142
143 let cache_path = dependencies_cache_path()?.join(self.game.dependencies_cache_file_name());
144 let cache_path = if only_parent_packs { None } else { Some(&*cache_path) };
145 let _ = self.load_dependencies(cache_path, true, settings);
146
147 Ok(DependenciesInfo::new(&self.dependencies, self.game.vanilla_db_table_name_logic()))
148 }
149
150 pub fn rebuild_dependencies_after_schema_update(&mut self, settings: &Settings) -> Result<()> {
156 if !self.dependencies.is_vanilla_data_loaded(false) {
157 return Ok(());
158 }
159
160 let cache_path = dependencies_cache_path()?.join(self.game.dependencies_cache_file_name());
161 self.load_dependencies(Some(&cache_path), true, settings)
162 .map_err(|_| anyhow!("Schema updated, but dependencies cache rebuilding failed. You may need to regenerate it."))
163 }
164
165 fn load_dependencies(&mut self, cache_path: Option<&Path>, decode_tables: bool, settings: &Settings) -> Result<()> {
177 let game_path = settings.path_buf(self.game.key());
178 let schema = if decode_tables { &self.schema } else { &None };
179 let result = self.dependencies.rebuild(schema, &parent_pack_names(&self.packs), cache_path, &self.game, &game_path, &settings.path_buf(SECONDARY_PATH));
180
181 match &result {
183 Err(_) if !game_path.is_dir() => self.dependencies_error = Some("The install folder of the game is not configured, or doesn't exist.".to_owned()),
184 Err(error) => self.dependencies_error = Some(error.to_string()),
185 Ok(()) if cache_path.is_some() => self.dependencies_error = None,
186 Ok(()) => {},
187 }
188
189 result.map_err(From::from)
190 }
191
192 pub fn dependencies_info(&self) -> DependenciesInfo {
194 DependenciesInfo::new(&self.dependencies, self.game.vanilla_db_table_name_logic())
195 }
196}