Skip to main content

mc_minder/config/
mod.rs

1use serde::Deserialize;
2use std::path::PathBuf;
3use anyhow::{Result, Context};
4
5#[derive(Debug, Deserialize, Clone)]
6pub struct Config {
7    pub rcon: RconConfig,
8    pub ai: Option<AiConfig>,
9    pub ollama: Option<OllamaConfig>,
10    #[serde(default)]
11    pub server: ServerConfig,
12    #[serde(default)]
13    pub backup: BackupConfig,
14    #[serde(default)]
15    pub notification: NotificationConfig,
16    #[serde(default)]
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 AiConfig {
66    pub api_url: String,
67    pub api_key: String,
68    #[serde(default = "default_model")]
69    pub model: String,
70    #[serde(default = "default_trigger")]
71    pub trigger: String,
72    #[serde(default = "default_max_tokens")]
73    pub max_tokens: u32,
74    #[serde(default = "default_temperature")]
75    pub temperature: f32,
76}
77
78fn default_model() -> String { "gpt-3.5-turbo".to_string() }
79fn default_trigger() -> String { "!".to_string() }
80fn default_max_tokens() -> u32 { 150 }
81fn default_temperature() -> f32 { 0.7 }
82
83#[derive(Debug, Deserialize, Clone)]
84pub struct OllamaConfig {
85    #[serde(default = "default_ollama_enabled")]
86    pub enabled: bool,
87    #[serde(default = "default_ollama_url")]
88    pub url: String,
89    #[serde(default = "default_ollama_model")]
90    pub model: String,
91}
92
93fn default_ollama_enabled() -> bool { false }
94fn default_ollama_url() -> String { "http://localhost:11434/api/generate".to_string() }
95fn default_ollama_model() -> String { "qwen:0.5b".to_string() }
96
97#[derive(Debug, Deserialize, Clone)]
98pub struct BackupConfig {
99    #[serde(default = "default_world_dir")]
100    pub world_dir: String,
101    #[serde(default = "default_backup_dest")]
102    pub backup_dest: String,
103    #[serde(default = "default_retain_days")]
104    pub retain_days: u32,
105}
106
107fn default_world_dir() -> String { "world".to_string() }
108fn default_backup_dest() -> String { "../backups".to_string() }
109fn default_retain_days() -> u32 { 7 }
110
111impl Default for BackupConfig {
112    fn default() -> Self {
113        Self {
114            world_dir: default_world_dir(),
115            backup_dest: default_backup_dest(),
116            retain_days: default_retain_days(),
117        }
118    }
119}
120
121#[derive(Debug, Deserialize, Clone)]
122pub struct NotificationConfig {
123    #[serde(default)]
124    pub telegram_bot_token: String,
125    #[serde(default)]
126    pub telegram_chat_id: String,
127    #[serde(default = "default_termux_notify")]
128    pub termux_notify: bool,
129}
130
131fn default_termux_notify() -> bool { true }
132
133impl Default for NotificationConfig {
134    fn default() -> Self {
135        Self {
136            telegram_bot_token: String::new(),
137            telegram_chat_id: String::new(),
138            termux_notify: default_termux_notify(),
139        }
140    }
141}
142
143#[derive(Debug, Deserialize, Clone)]
144pub struct JvmConfig {
145    #[serde(default = "default_gc")]
146    pub gc: String,
147    #[serde(default)]
148    pub extra_flags: String,
149    #[serde(default)]
150    pub xmx: Option<String>,
151    #[serde(default)]
152    pub xms: Option<String>,
153}
154
155fn default_gc() -> String { "G1GC".to_string() }
156
157impl Default for JvmConfig {
158    fn default() -> Self {
159        Self {
160            gc: default_gc(),
161            extra_flags: String::new(),
162            xmx: None,
163            xms: None,
164        }
165    }
166}
167
168impl Config {
169    pub fn load(path: &PathBuf) -> Result<Self> {
170        let content = std::fs::read_to_string(path)
171            .with_context(|| format!("Failed to read config file: {:?}", path))?;
172        
173        Self::load_from_str(&content)
174    }
175
176    pub fn load_from_str(content: &str) -> Result<Self> {
177        let mut config: Config = toml::from_str(content)
178            .with_context(|| "Failed to parse config file")?;
179        
180        if let Some(ref ai) = config.ai {
181            if ai.api_key.is_empty() || ai.api_url.is_empty() {
182                config.ai = None;
183            }
184        }
185        
186        Ok(config)
187    }
188
189    pub fn generate_template() -> String {
190        r#"# MC-Minder Configuration File
191# MC-Minder 配置文件
192
193# Server Configuration
194# 服务器配置
195[server]
196jar = "fabric-server.jar"
197min_mem = "512M"
198max_mem = "1G"
199session_name = "mc_server"
200log_file = "logs/latest.log"
201
202# RCON Configuration - Required for MC-Minder to communicate with Minecraft server
203# RCON 配置 - MC-Minder 与 Minecraft 服务器通信必需
204[rcon]
205host = "127.0.0.1"
206port = 25575
207password = "your_rcon_password"
208
209# AI Configuration - Leave empty or remove this section to disable AI features
210# AI 配置 - 留空或删除此部分可禁用 AI 功能
211[ai]
212api_url = ""
213api_key = ""
214model = "gpt-3.5-turbo"
215trigger = "!"
216max_tokens = 150
217temperature = 0.7
218
219# Ollama Configuration - Set enabled = true to use local AI
220# Ollama 配置 - 设置 enabled = true 使用本地 AI
221[ollama]
222enabled = false
223url = "http://localhost:11434/api/generate"
224model = "qwen:0.5b"
225
226# Backup Configuration
227# 备份配置
228[backup]
229world_dir = "world"
230backup_dest = "../backups"
231retain_days = 7
232
233# Notification Configuration - Leave empty to disable notifications
234# 通知配置 - 留空禁用通知功能
235[notification]
236telegram_bot_token = ""
237telegram_chat_id = ""
238termux_notify = true
239
240# JVM Configuration - Advanced JVM tuning options
241# JVM 配置 - 高级 JVM 调优选项
242[jvm]
243gc = "G1GC"
244extra_flags = ""
245# xmx = "2G"  # Uncomment to override server.max_mem
246# xms = "512M"  # Uncomment to override server.min_mem
247"#.to_string()
248    }
249}