veloren_server_cli/
settings.rs1use serde::{Deserialize, Serialize};
2use std::{
3 fs,
4 net::{Ipv4Addr, SocketAddr},
5 path::PathBuf,
6};
7use tracing::warn;
8
9#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
10#[expect(clippy::upper_case_acronyms)]
11pub enum ShutdownSignal {
12 SIGUSR1,
13 SIGUSR2,
14 SIGTERM,
15}
16
17impl ShutdownSignal {
18 #[cfg(any(target_os = "linux", target_os = "macos"))]
19 pub fn to_signal(self) -> core::ffi::c_int {
20 match self {
21 Self::SIGUSR1 => signal_hook::consts::SIGUSR1,
22 Self::SIGUSR2 => signal_hook::consts::SIGUSR2,
23 Self::SIGTERM => signal_hook::consts::SIGTERM,
24 }
25 }
26}
27
28#[derive(Clone, Debug, Serialize, Deserialize)]
29#[serde(default)]
30pub struct Settings {
31 pub update_shutdown_grace_period_secs: u32,
32 pub update_shutdown_message: String,
33 pub web_address: SocketAddr,
34 pub web_chat_secret: Option<String>,
37 pub ui_api_secret: Option<String>,
40 pub shutdown_signals: Vec<ShutdownSignal>,
41}
42
43impl Default for Settings {
44 fn default() -> Self {
45 Self {
46 update_shutdown_grace_period_secs: 120,
47 update_shutdown_message: "The server is restarting for an update".to_owned(),
48 web_address: SocketAddr::from((Ipv4Addr::LOCALHOST, 14005)),
49 web_chat_secret: None,
50 ui_api_secret: None,
51 shutdown_signals: if cfg!(any(target_os = "linux", target_os = "macos")) {
52 vec![ShutdownSignal::SIGUSR1]
53 } else {
54 Vec::new()
55 },
56 }
57 }
58}
59
60impl Settings {
61 pub fn load() -> Self {
62 let path = Self::get_settings_path();
63
64 if let Ok(file) = fs::File::open(&path) {
65 match ron::de::from_reader(file) {
66 Ok(s) => return s,
67 Err(e) => {
68 warn!(?e, "Failed to parse setting file! Fallback to default.");
69 let mut new_path = path.to_owned();
71 new_path.pop();
72 new_path.push("settings.invalid.ron");
73 if let Err(e) = fs::rename(&path, &new_path) {
74 warn!(?e, ?path, ?new_path, "Failed to rename settings file.");
75 }
76 },
77 }
78 }
79 let default_settings = Self::default();
83 default_settings.save_to_file_warn();
84 default_settings
85 }
86
87 fn save_to_file_warn(&self) {
88 if let Err(e) = self.save_to_file() {
89 warn!(?e, "Failed to save settings");
90 }
91 }
92
93 fn save_to_file(&self) -> std::io::Result<()> {
94 let path = Self::get_settings_path();
95 if let Some(dir) = path.parent() {
96 fs::create_dir_all(dir)?;
97 }
98
99 let ron = ron::ser::to_string_pretty(self, ron::ser::PrettyConfig::default()).unwrap();
100 fs::write(path, ron.as_bytes())
101 }
102
103 pub fn get_settings_path() -> PathBuf {
104 let mut path = data_dir();
105 path.push("settings.ron");
106 path
107 }
108}
109
110pub fn data_dir() -> PathBuf {
111 let mut path = common_base::userdata_dir_workspace!();
112 path.push("server-cli");
113 path
114}