csgo_gsi_builder/lib.rs
1//! CSGO Game State Integration builder
2//!
3//! CSGO Game State Integration configuration file builder and installer.
4//!
5//! # Exemples
6//!
7//! You can use one of the ready made components:
8//!
9//! ```no_run
10//! use csgo_gsi_builder::{config::Config, Builder, Components};
11//!
12//! let mut config_builder = Builder::with_config(Config {
13//! name: String::from("my_gsi_config_file"),
14//! data: Components::ALL.into(),
15//! ..Default::default()
16//! });
17//! config_builder
18//! .build()
19//! .install("C:\\Counter-Strike Global Offensive\\csgo\\cfg")
20//! .unwrap();
21//! ```
22//!
23//! Or create your own set of components:
24//!
25//! ```no_run
26//! use csgo_gsi_builder::{
27//! config::{Config, Data},
28//! Builder, Components,
29//! };
30//!
31//! let components: &[Components] = &[Components::Provider, Components::PlayerId];
32//! let mut config_builder = Builder::with_config(Config {
33//! name: String::from("my_gsi_config_file"),
34//! data: Data::from(components),
35//! ..Default::default()
36//! });
37//! config_builder
38//! .build()
39//! .install("C:\\Counter-Strike Global Offensive\\csgo\\cfg")
40//! .unwrap();
41//! ```
42//!
43//! # auto-install support
44//!
45//! You can enable the `auto_install` feature to install automatically the
46//! config into CSGO's cfg folder
47//!
48//! ```no_run
49//! use csgo_gsi_builder::{config::Config, Builder, Components};
50//!
51//! let mut config_builder = Builder::with_config(Config {
52//! name: String::from("my_gsi_config_file"),
53//! data: Components::ALL.into(),
54//! ..Default::default()
55//! });
56//! config_builder.build().auto_install().unwrap();
57//! ```
58
59mod components;
60pub use components::Components; // re-export to avoid repetition
61
62pub mod config;
63
64use std::fs;
65use std::path::PathBuf;
66
67use crate::config::Config;
68
69#[derive(Default)]
70pub struct Builder {
71 config: Config,
72 output: String,
73}
74
75impl Builder {
76 /// Creates a config file builder based on a [`Config`].
77 pub fn with_config(config: Config) -> Self {
78 Self {
79 config,
80 ..Default::default()
81 }
82 }
83
84 /// Serializes the [`Config`] to a string ready to be written in a cfg file.
85 pub fn build(&mut self) -> &mut Self {
86 self.output = vdf_serde::to_string(&self.config).unwrap();
87 self
88 }
89
90 /// Gets the serialized [`Config`].
91 ///
92 /// This method must only be called after `build`.
93 pub fn output(&self) -> String {
94 self.output.clone()
95 }
96
97 /// Write the serialized [`Config`] to a cfg file at the path passed in
98 /// argument.
99 pub fn install<P: Into<PathBuf>>(
100 &self,
101 folder_path: P,
102 ) -> Result<(), Box<dyn std::error::Error>> {
103 assert!(
104 !self.output.is_empty(),
105 "config should be build before installing"
106 );
107
108 let mut path: PathBuf = folder_path.into();
109
110 let folder_path = path.as_path();
111 let metadata = fs::metadata(folder_path)?;
112 if !metadata.is_dir() {
113 return Err(format!("{} is not a directory", folder_path.to_string_lossy()).into());
114 }
115
116 path.push(&format!("gamestate_integration_{}.cfg", self.config.name));
117 fs::write(path, self.output.as_bytes())?;
118
119 Ok(())
120 }
121
122 /// Automatically find the CSGO install directory and write the serialized.
123 /// [`Config`] to a cfg file
124 #[cfg(feature = "auto_install")]
125 pub fn auto_install(&self) -> Result<(), Box<dyn std::error::Error>> {
126 let mut steam_dir =
127 steamlocate::SteamDir::locate().ok_or("could not locate steam install directory")?;
128 match steam_dir.app(&730) {
129 None => Err("could not locate CSGO install directory".into()),
130 Some(csgo) => {
131 let mut csgo_path = csgo.path.clone();
132 csgo_path.push("csgo");
133 csgo_path.push("cfg");
134
135 self.install(csgo_path)
136 }
137 }
138 }
139}