use std::{ collections::VecDeque, net::SocketAddr, time::{Duration, Instant, SystemTime, UNIX_EPOCH}, }; use godot::{ classes::{FileAccess, file_access::ModeFlags}, prelude::*, tools::get_autoload_by_name, }; use serde::{Deserialize, Serialize}; pub const NETWORK_SINGLETON_NAME: &str = "GameSettingsGlobal"; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GameSettings { pub fov: f64, pub default_name: String, pub recent_servers: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RecentServer { pub addr: SocketAddr, pub visited: u128, } impl Default for GameSettings { fn default() -> Self { Self { fov: 90., default_name: "Default McGee".to_owned(), recent_servers: Vec::new(), } } } #[derive(GodotClass)] #[class(base=Node)] pub struct GameSettingsManager { pub settings: GameSettings, base: Base, } #[godot_api] impl INode for GameSettingsManager { fn init(base: Base) -> GameSettingsManager { let mut settings = GameSettings::default(); if let Some(file) = FileAccess::open("user://config.toml", ModeFlags::READ) { if let Ok(deserialized) = toml::from_str(&file.get_as_text().to_string()) { settings = deserialized; } } GameSettingsManager { settings, base } } } #[godot_api] impl GameSettingsManager { #[signal] pub fn on_settings_changed(); pub fn singleton() -> Gd { get_autoload_by_name::(NETWORK_SINGLETON_NAME) } pub fn update_settings(&mut self, settings: GameSettings) { self.settings = settings; if let Some(mut file) = FileAccess::open("user://config.toml", ModeFlags::WRITE) { if let Ok(serialized) = toml::to_string(&self.settings) { file.store_string(&serialized); } } self.run_deferred(|s| s.signals().on_settings_changed().emit()); } pub fn visit_server(&mut self, server: SocketAddr) { if let Some(server) = self .settings .recent_servers .iter_mut() .find(|s| s.addr == server) { server.visited = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or(Duration::from_millis(0)) .as_nanos(); } else { self.settings.recent_servers.push(RecentServer { addr: server, visited: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or(Duration::from_millis(0)) .as_nanos(), }); } let mut servers = self.settings.recent_servers.clone(); servers.sort_by_key(|s| s.visited); servers = servers.into_iter().rev().collect(); while servers.len() > 10 { servers.remove(0); } let settings = GameSettings { recent_servers: servers, ..self.settings.clone() }; self.update_settings(settings); } }