1use smallvec::SmallVec;
2
3pub mod bethesda;
4pub mod cyberpunk;
5pub mod detection;
6pub mod generic;
7pub mod launcher;
8pub mod tools;
9pub mod traits;
10pub mod ue4;
11
12pub use detection::{find_detected_game, scan_installed_games, DetectedGame, LauncherSource};
13pub use traits::{
14 GamePlugin, ModClassifyConfig, ModSafety, SaveTracker, classify_mod_by_content,
15 DiscoveredFile, DiscoveredMod, ModScanner, ModSource, ScanContext,
16 walk_files_relative, slug,
17};
18
19pub fn game_probe(
33 plugin: &'static dyn GamePlugin,
34) -> modde_core::installer::InstallProbe {
35 modde_core::installer::InstallProbe::new(
36 move |dir: &std::path::Path| plugin.analyze_mod_archive(dir),
37 move |dir: &std::path::Path| plugin.recognizes_bare_layout(dir),
38 )
39}
40
41pub const SUPPORTED_GAME_IDS: &[&str] = &[
43 "skyrim-se",
44 "skyrim-ae",
45 "fallout4",
46 "fallout76",
47 "starfield",
48 "cyberpunk2077",
49 "stellar-blade",
50];
51
52pub fn supported_games() -> SmallVec<[(&'static str, &'static str); 8]> {
54 SUPPORTED_GAME_IDS
55 .iter()
56 .filter_map(|&id| resolve_game_plugin(id).map(|p| (p.game_id(), p.display_name())))
57 .collect()
58}
59
60pub fn normalize_wabbajack_game(wj_game: &str) -> Option<&'static str> {
65 match wj_game {
66 "Cyberpunk2077" => Some("cyberpunk2077"),
67 "SkyrimSpecialEdition" => Some("skyrim-se"),
68 "Fallout4" => Some("fallout4"),
69 "Fallout76" => Some("fallout76"),
70 "Starfield" => Some("starfield"),
71 _ => None,
72 }
73}
74
75pub fn resolve_game_plugin(game_id: &str) -> Option<&'static dyn GamePlugin> {
77 match game_id {
78 "skyrim-se" => Some(&bethesda::SKYRIM_SE),
79 "skyrim-ae" => Some(&bethesda::SKYRIM_AE),
80 "fallout4" => Some(&bethesda::FALLOUT4),
81 "fallout76" => Some(&bethesda::FALLOUT76),
82 "starfield" => Some(&bethesda::STARFIELD),
83 "cyberpunk2077" => Some(&cyberpunk::CYBERPUNK2077),
84 "stellar-blade" => Some(&ue4::STELLAR_BLADE),
85 _ => None,
86 }
87}
88
89pub fn resolve_mod_scanner(game_id: &str) -> Option<&'static dyn ModScanner> {
91 match game_id {
92 "cyberpunk2077" => Some(&cyberpunk::scanner::CYBERPUNK_SCANNER),
93 "skyrim-se" | "skyrim-ae" => Some(&bethesda::scanner::SKYRIM_SCANNER),
94 "fallout4" => Some(&bethesda::scanner::FALLOUT4_SCANNER),
95 "starfield" => Some(&bethesda::scanner::STARFIELD_SCANNER),
96 "stellar-blade" => Some(&ue4::scanner::STELLAR_BLADE_SCANNER),
97 _ => None,
98 }
99}
100
101pub fn resolve_collision_classifier(
103 game_id: &str,
104) -> Option<Box<dyn modde_core::collision::CollisionClassifier>> {
105 match game_id {
106 "skyrim-se" | "skyrim-ae" | "fallout4" | "fallout76" | "starfield" => {
107 Some(Box::new(bethesda::collision::BethesdaCollisionClassifier))
108 }
109 "cyberpunk2077" => Some(Box::new(cyberpunk::collision::CyberpunkCollisionClassifier)),
110 _ => None,
111 }
112}
113
114pub fn resolve_save_tracker(game_id: &str) -> Option<&'static dyn SaveTracker> {
116 match game_id {
117 "skyrim-se" | "skyrim-ae" => Some(&bethesda::saves::SKYRIM_SAVE_TRACKER),
118 "fallout4" => Some(&bethesda::saves::FALLOUT4_SAVE_TRACKER),
119 "fallout76" => Some(&bethesda::saves::FALLOUT76_SAVE_TRACKER),
121 "starfield" => Some(&bethesda::saves::SKYRIM_SAVE_TRACKER),
123 "cyberpunk2077" => Some(&cyberpunk::saves::CYBERPUNK_SAVE_TRACKER),
124 _ => None,
125 }
126}