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    /// Server type: fabric, paper, vanilla, forge, etc. (reserved for future multi-type support)
45    #[serde(default = "default_server_type")]
46    #[allow(dead_code)]
47    pub server_type: String,
48}
49
50fn default_jar() -> String { "fabric-server.jar".to_string() }
51fn default_min_mem() -> String { "512M".to_string() }
52fn default_max_mem() -> String { "1G".to_string() }
53fn default_session_name() -> String { "mc_server".to_string() }
54fn default_log_file() -> String { "logs/latest.log".to_string() }
55fn default_server_type() -> String { "fabric".to_string() }
56
57impl Default for ServerConfig {
58    fn default() -> Self {
59        Self {
60            jar: default_jar(),
61            min_mem: default_min_mem(),
62            max_mem: default_max_mem(),
63            session_name: default_session_name(),
64            log_file: default_log_file(),
65            server_type: default_server_type(),
66        }
67    }
68}
69
70#[derive(Debug, Deserialize, Clone)]
71pub struct BackupConfig {
72    #[serde(default = "default_world_dir")]
73    pub world_dir: String,
74    #[serde(default = "default_backup_dest")]
75    pub backup_dest: String,
76    #[serde(default = "default_retain_days")]
77    pub retain_days: u32,
78}
79
80fn default_world_dir() -> String { "world".to_string() }
81fn default_backup_dest() -> String { "../backups".to_string() }
82fn default_retain_days() -> u32 { 7 }
83
84impl Default for BackupConfig {
85    fn default() -> Self {
86        Self {
87            world_dir: default_world_dir(),
88            backup_dest: default_backup_dest(),
89            retain_days: default_retain_days(),
90        }
91    }
92}
93
94#[derive(Debug, Deserialize, Clone)]
95#[allow(dead_code)]
96pub struct NotificationConfig {
97    #[serde(default)]
98    pub telegram_bot_token: String,
99    #[serde(default)]
100    pub telegram_chat_id: String,
101    #[serde(default = "default_termux_notify")]
102    pub termux_notify: bool,
103}
104
105fn default_termux_notify() -> bool { true }
106
107impl Default for NotificationConfig {
108    fn default() -> Self {
109        Self {
110            telegram_bot_token: String::new(),
111            telegram_chat_id: String::new(),
112            termux_notify: default_termux_notify(),
113        }
114    }
115}
116
117#[derive(Debug, Deserialize, Clone)]
118#[allow(dead_code)]
119pub struct JvmConfig {
120    #[serde(default = "default_gc")]
121    pub gc: String,
122    #[serde(default)]
123    pub extra_flags: String,
124    #[serde(default)]
125    pub xmx: Option<String>,
126    #[serde(default)]
127    pub xms: Option<String>,
128    #[serde(default)]
129    pub jdk_path: Option<String>,
130}
131
132fn default_gc() -> String { "G1GC".to_string() }
133
134impl Default for JvmConfig {
135    fn default() -> Self {
136        Self {
137            gc: default_gc(),
138            extra_flags: String::new(),
139            xmx: None,
140            xms: None,
141            jdk_path: None,
142        }
143    }
144}
145
146impl Config {
147    pub fn load(path: &PathBuf) -> Result<Self> {
148        let content = std::fs::read_to_string(path)
149            .with_context(|| format!("Failed to read config file: {:?}", path))?;
150        
151        Self::load_from_str(&content)
152    }
153
154    pub fn load_from_str(content: &str) -> Result<Self> {
155        let config: Config = toml::from_str(content)
156            .with_context(|| "Failed to parse config file")?;
157        
158        Ok(config)
159    }
160
161    pub fn generate_template() -> String {
162        let s = r#"# MC-Minder Configuration File
163
164[server]
165jar = "fabric-server.jar"
166min_mem = "512M"
167max_mem = "1G"
168session_name = "mc_server"
169log_file = "logs/latest.log"
170
171[rcon]
172host = "127.0.0.1"
173port = 25575
174password = ""
175
176[backup]
177world_dir = "world"
178backup_dest = "../backups"
179retain_days = 7
180
181[notification]
182telegram_bot_token = ""
183telegram_chat_id = ""
184termux_notify = true
185
186[jvm]
187gc = "G1GC"
188extra_flags = ""
189# jdk_path = "/usr/lib/jvm/java-17-openjdk/bin/java"
190"#;
191        s.to_string()
192    }
193}