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