Skip to main content

rpfm_extensions/diagnostics/
config.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11//! Module with the structs and functions specific for `Config` diagnostics.
12
13use getset::{Getters, MutGetters};
14use serde_derive::{Serialize, Deserialize};
15
16use std::{fmt, fmt::Display};
17use std::path::Path;
18
19use rpfm_lib::games::GameInfo;
20
21use crate::diagnostics::*;
22
23//-------------------------------------------------------------------------------//
24//                              Enums & Structs
25//-------------------------------------------------------------------------------//
26
27/// This struct contains the results of a Config diagnostic.
28#[derive(Debug, Clone, Default, Getters, MutGetters, Serialize, Deserialize)]
29#[getset(get = "pub", get_mut = "pub")]
30pub struct ConfigDiagnostic {
31    results: Vec<ConfigDiagnosticReport>
32}
33
34/// This struct defines an individual config diagnostic result.
35#[derive(Debug, Clone, Getters, MutGetters, Serialize, Deserialize)]
36#[getset(get = "pub", get_mut = "pub")]
37pub struct ConfigDiagnosticReport {
38    report_type: ConfigDiagnosticReportType,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
42pub enum ConfigDiagnosticReportType {
43    DependenciesCacheNotGenerated,
44    DependenciesCacheOutdated,
45    DependenciesCacheCouldNotBeLoaded(String),
46    IncorrectGamePath,
47}
48
49//-------------------------------------------------------------------------------//
50//                             Implementations
51//-------------------------------------------------------------------------------//
52
53impl ConfigDiagnosticReport {
54    pub fn new(report_type: ConfigDiagnosticReportType) -> Self {
55        Self {
56            report_type
57        }
58    }
59}
60
61impl DiagnosticReport for ConfigDiagnosticReport {
62    fn message(&self) -> String {
63        match self.report_type {
64            ConfigDiagnosticReportType::DependenciesCacheNotGenerated => "Dependency Cache not generated for the currently selected game.".to_owned(),
65            ConfigDiagnosticReportType::DependenciesCacheOutdated => "Dependency Cache for the selected game is outdated and could not be loaded.".to_owned(),
66            ConfigDiagnosticReportType::DependenciesCacheCouldNotBeLoaded(_) => "Dependency Cache couldn't be loaded for the game selected, due to errors reading the game's folder.".to_owned(),
67            ConfigDiagnosticReportType::IncorrectGamePath => "Game Path for the current Game Selected is incorrect.".to_owned(),
68        }
69    }
70
71    fn level(&self) -> DiagnosticLevel {
72        match self.report_type {
73            ConfigDiagnosticReportType::DependenciesCacheNotGenerated => DiagnosticLevel::Error,
74            ConfigDiagnosticReportType::DependenciesCacheOutdated => DiagnosticLevel::Error,
75            ConfigDiagnosticReportType::DependenciesCacheCouldNotBeLoaded(_) => DiagnosticLevel::Error,
76            ConfigDiagnosticReportType::IncorrectGamePath => DiagnosticLevel::Error,
77        }
78    }
79}
80
81impl Display for ConfigDiagnosticReportType {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        Display::fmt(match self {
84            Self::DependenciesCacheNotGenerated => "DependenciesCacheNotGenerated",
85            Self::DependenciesCacheOutdated => "DependenciesCacheOutdated",
86            Self::DependenciesCacheCouldNotBeLoaded(_) => "DependenciesCacheCouldNotBeLoaded",
87            Self::IncorrectGamePath => "IncorrectGamePath",
88        }, f)
89    }
90}
91
92impl ConfigDiagnostic {
93
94    /// This function takes care of checking RPFM's configuration for errors.
95    pub fn check(dependencies: &Dependencies, game_info: &GameInfo, game_path: &Path) -> Option<DiagnosticType> {
96        let mut diagnostic = ConfigDiagnostic::default();
97
98        // First, check if we have the game folder correctly configured. We can't do anything without it.
99        let exe_path = game_info.executable_path(game_path).filter(|path| path.is_file());
100        if exe_path.is_none() {
101            diagnostic.results_mut().push(ConfigDiagnosticReport::new(ConfigDiagnosticReportType::IncorrectGamePath));
102        }
103
104        // If we have the correct folder, check if the vanilla data of the dependencies is loaded.
105        else if !dependencies.is_vanilla_data_loaded(false) {
106            diagnostic.results_mut().push(ConfigDiagnosticReport::new(ConfigDiagnosticReportType::DependenciesCacheNotGenerated));
107        }
108
109        // If we have vanilla data, check if the dependencies need updating due to changes in the game files.
110        else {
111            match dependencies.needs_updating(game_info, game_path) {
112                Ok(needs_updating) => {
113                    if needs_updating {
114                        diagnostic.results_mut().push(ConfigDiagnosticReport::new(ConfigDiagnosticReportType::DependenciesCacheOutdated));
115                    }
116                }
117
118                Err(error) => {
119                    diagnostic.results_mut().push(ConfigDiagnosticReport::new(ConfigDiagnosticReportType::DependenciesCacheCouldNotBeLoaded(error.to_string())));
120                }
121            }
122        }
123
124        if !diagnostic.results().is_empty() {
125            Some(DiagnosticType::Config(diagnostic))
126        } else { None }
127    }
128}