Skip to main content

mc_minder/config/
mod.rs

1use serde::Deserialize;
2use std::path::PathBuf;
3use anyhow::{Result, Context};
4// use log::warn;
5
6#[derive(Debug, Deserialize, Clone)]
7pub struct Config {
8    pub rcon: RconConfig,
9    #[serde(default)]
10    pub server: ServerConfig,
11    #[serde(default)]
12    pub backup: BackupConfig,
13    #[serde(default)]
14    pub notification: NotificationConfig,
15    #[serde(default)]
16    #[allow(dead_code)]
17    pub jvm: JvmConfig,
18}
19
20#[derive(Debug, Deserialize, Clone)]
21pub struct RconConfig {
22    #[serde(default = "default_rcon_host")]
23    pub host: String,
24    #[serde(default = "default_rcon_port")]
25    pub port: u16,
26    pub password: String,
27}
28
29fn default_rcon_host() -> String { "127.0.0.1".to_string() }
30fn default_rcon_port() -> u16 { 25575 }
31
32#[derive(Debug, Deserialize, Clone)]
33pub struct ServerConfig {
34    #[serde(default = "default_jar")]
35    pub jar: String,
36    #[serde(default = "default_min_mem")]
37    pub min_mem: String,
38    #[serde(default = "default_max_mem")]
39    pub max_mem: String,
40    #[serde(default = "default_session_name")]
41    pub session_name: String,
42    #[serde(default = "default_log_file")]
43    pub log_file: String,
44}
45
46fn default_jar() -> String { "fabric-server.jar".to_string() }
47fn default_min_mem() -> String { "512M".to_string() }
48fn default_max_mem() -> String { "1G".to_string() }
49fn default_session_name() -> String { "mc_server".to_string() }
50fn default_log_file() -> String { "logs/latest.log".to_string() }
51
52impl Default for ServerConfig {
53    fn default() -> Self {
54        Self {
55            jar: default_jar(),
56            min_mem: default_min_mem(),
57            max_mem: default_max_mem(),
58            session_name: default_session_name(),
59            log_file: default_log_file(),
60        }
61    }
62}
63
64#[derive(Debug, Deserialize, Clone)]
65pub struct BackupConfig {
66    #[serde(default = "default_world_dir")]
67    pub world_dir: String,
68    #[serde(default = "default_backup_dest")]
69    pub backup_dest: String,
70    #[serde(default = "default_retain_days")]
71    pub retain_days: u32,
72}
73
74fn default_world_dir() -> String { "world".to_string() }
75fn default_backup_dest() -> String { "../backups".to_string() }
76fn default_retain_days() -> u32 { 7 }
77
78impl Default for BackupConfig {
79    fn default() -> Self {
80        Self {
81            world_dir: default_world_dir(),
82            backup_dest: default_backup_dest(),
83            retain_days: default_retain_days(),
84        }
85    }
86}
87
88#[derive(Debug, Deserialize, Clone)]
89#[allow(dead_code)]
90pub struct NotificationConfig {
91    #[serde(default)]
92    pub telegram_bot_token: String,
93    #[serde(default)]
94    pub telegram_chat_id: String,
95    #[serde(default = "default_termux_notify")]
96    pub termux_notify: bool,
97}
98
99fn default_termux_notify() -> bool { true }
100
101impl Default for NotificationConfig {
102    fn default() -> Self {
103        Self {
104            telegram_bot_token: String::new(),
105            telegram_chat_id: String::new(),
106            termux_notify: default_termux_notify(),
107        }
108    }
109}
110
111#[derive(Debug, Deserialize, Clone)]
112#[allow(dead_code)]
113pub struct JvmConfig {
114    #[serde(default = "default_gc")]
115    pub gc: String,
116    #[serde(default)]
117    pub extra_flags: String,
118    #[serde(default)]
119    pub xmx: Option<String>,
120    #[serde(default)]
121    pub xms: Option<String>,
122    #[serde(default)]
123    pub jdk_path: Option<String>,
124}
125
126fn default_gc() -> String { "G1GC".to_string() }
127
128impl Default for JvmConfig {
129    fn default() -> Self {
130        Self {
131            gc: default_gc(),
132            extra_flags: String::new(),
133            xmx: None,
134            xms: None,
135            jdk_path: None,
136        }
137    }
138}
139
140impl Config {
141    pub fn load(path: &PathBuf) -> Result<Self> {
142        let content = std::fs::read_to_string(path)
143            .with_context(|| format!("Failed to read config file: {:?}", path))?;
144        
145        Self::load_from_str(&content)
146    }
147
148    pub fn load_from_str(content: &str) -> Result<Self> {
149        let config: Config = toml::from_str(content)
150            .with_context(|| "Failed to parse config file")?;
151        
152        Ok(config)
153    }
154
155    pub fn generate_template() -> String {
156        let s = r#"# MC-Minder Configuration File
157
158[server]
159jar = "fabric-server.jar"
160min_mem = "512M"
161max_mem = "1G"
162session_name = "mc_server"
163log_file = "logs/latest.log"
164
165[rcon]
166host = "127.0.0.1"
167port = 25575
168password = ""
169
170[backup]
171world_dir = "world"
172backup_dest = "../backups"
173retain_days = 7
174
175[notification]
176telegram_bot_token = ""
177telegram_chat_id = ""
178termux_notify = true
179
180[jvm]
181gc = "G1GC"
182extra_flags = ""
183# jdk_path = "/usr/lib/jvm/java-17-openjdk/bin/java"
184"#;
185        s.to_string()
186    }
187}