2019-08-18 18:07:21 +00:00
|
|
|
use crate::{
|
2019-10-23 19:40:45 +00:00
|
|
|
hud::{BarNumbers, CrosshairType, Intro, ShortcutNumbers, XpBar},
|
2019-09-26 07:28:40 +00:00
|
|
|
render::AaMode,
|
2019-08-18 18:07:21 +00:00
|
|
|
ui::ScaleMode,
|
|
|
|
window::KeyMouse,
|
|
|
|
};
|
2019-04-25 16:24:00 +00:00
|
|
|
use directories::ProjectDirs;
|
2019-05-25 14:39:27 +00:00
|
|
|
use glutin::{MouseButton, VirtualKeyCode};
|
2019-07-26 02:28:53 +00:00
|
|
|
use log::warn;
|
2019-04-25 16:24:00 +00:00
|
|
|
use serde_derive::{Deserialize, Serialize};
|
2019-05-20 21:32:16 +00:00
|
|
|
use std::{fs, io::prelude::*, path::PathBuf};
|
2019-04-15 17:51:26 +00:00
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
/// `ControlSettings` contains keybindings.
|
2019-04-15 17:51:26 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2019-06-08 23:35:23 +00:00
|
|
|
#[serde(default)]
|
2019-04-15 17:51:26 +00:00
|
|
|
pub struct ControlSettings {
|
2019-08-30 22:13:45 +00:00
|
|
|
pub primary: KeyMouse,
|
|
|
|
pub secondary: KeyMouse,
|
2019-05-25 14:39:27 +00:00
|
|
|
pub toggle_cursor: KeyMouse,
|
|
|
|
pub escape: KeyMouse,
|
|
|
|
pub enter: KeyMouse,
|
2019-07-05 16:21:11 +00:00
|
|
|
pub command: KeyMouse,
|
2019-05-25 14:39:27 +00:00
|
|
|
pub move_forward: KeyMouse,
|
|
|
|
pub move_left: KeyMouse,
|
|
|
|
pub move_back: KeyMouse,
|
|
|
|
pub move_right: KeyMouse,
|
|
|
|
pub jump: KeyMouse,
|
2019-09-09 19:11:40 +00:00
|
|
|
pub sit: KeyMouse,
|
2019-05-25 14:39:27 +00:00
|
|
|
pub glide: KeyMouse,
|
2019-09-09 19:11:40 +00:00
|
|
|
pub climb: KeyMouse,
|
|
|
|
pub climb_down: KeyMouse,
|
|
|
|
pub wall_leap: KeyMouse,
|
|
|
|
pub mount: KeyMouse,
|
2019-05-25 14:39:27 +00:00
|
|
|
pub map: KeyMouse,
|
|
|
|
pub bag: KeyMouse,
|
|
|
|
pub quest_log: KeyMouse,
|
|
|
|
pub character_window: KeyMouse,
|
|
|
|
pub social: KeyMouse,
|
|
|
|
pub spellbook: KeyMouse,
|
|
|
|
pub settings: KeyMouse,
|
|
|
|
pub help: KeyMouse,
|
|
|
|
pub toggle_interface: KeyMouse,
|
|
|
|
pub toggle_debug: KeyMouse,
|
|
|
|
pub fullscreen: KeyMouse,
|
|
|
|
pub screenshot: KeyMouse,
|
2019-05-25 22:00:38 +00:00
|
|
|
pub toggle_ingame_ui: KeyMouse,
|
2019-06-11 04:08:55 +00:00
|
|
|
pub roll: KeyMouse,
|
2019-08-27 11:42:17 +00:00
|
|
|
pub respawn: KeyMouse,
|
2019-07-29 16:19:08 +00:00
|
|
|
pub interact: KeyMouse,
|
2019-06-05 15:57:48 +00:00
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
impl Default for ControlSettings {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
2019-08-30 22:13:45 +00:00
|
|
|
primary: KeyMouse::Mouse(MouseButton::Left),
|
|
|
|
secondary: KeyMouse::Mouse(MouseButton::Right),
|
2019-06-08 23:35:23 +00:00
|
|
|
toggle_cursor: KeyMouse::Key(VirtualKeyCode::Tab),
|
|
|
|
escape: KeyMouse::Key(VirtualKeyCode::Escape),
|
|
|
|
enter: KeyMouse::Key(VirtualKeyCode::Return),
|
2019-07-05 16:21:11 +00:00
|
|
|
command: KeyMouse::Key(VirtualKeyCode::Slash),
|
2019-06-08 23:35:23 +00:00
|
|
|
move_forward: KeyMouse::Key(VirtualKeyCode::W),
|
|
|
|
move_left: KeyMouse::Key(VirtualKeyCode::A),
|
|
|
|
move_back: KeyMouse::Key(VirtualKeyCode::S),
|
|
|
|
move_right: KeyMouse::Key(VirtualKeyCode::D),
|
|
|
|
jump: KeyMouse::Key(VirtualKeyCode::Space),
|
2019-09-09 19:11:40 +00:00
|
|
|
sit: KeyMouse::Key(VirtualKeyCode::K),
|
2019-06-08 23:35:23 +00:00
|
|
|
glide: KeyMouse::Key(VirtualKeyCode::LShift),
|
2019-10-14 10:22:48 +00:00
|
|
|
climb: KeyMouse::Key(VirtualKeyCode::Space),
|
2019-09-27 16:04:22 +00:00
|
|
|
climb_down: KeyMouse::Key(VirtualKeyCode::LControl),
|
2019-09-09 19:11:40 +00:00
|
|
|
wall_leap: KeyMouse::Mouse(MouseButton::Middle),
|
|
|
|
mount: KeyMouse::Key(VirtualKeyCode::F),
|
2019-06-08 23:35:23 +00:00
|
|
|
map: KeyMouse::Key(VirtualKeyCode::M),
|
|
|
|
bag: KeyMouse::Key(VirtualKeyCode::B),
|
|
|
|
quest_log: KeyMouse::Key(VirtualKeyCode::L),
|
|
|
|
character_window: KeyMouse::Key(VirtualKeyCode::C),
|
|
|
|
social: KeyMouse::Key(VirtualKeyCode::O),
|
|
|
|
spellbook: KeyMouse::Key(VirtualKeyCode::P),
|
|
|
|
settings: KeyMouse::Key(VirtualKeyCode::N),
|
|
|
|
help: KeyMouse::Key(VirtualKeyCode::F1),
|
|
|
|
toggle_interface: KeyMouse::Key(VirtualKeyCode::F2),
|
|
|
|
toggle_debug: KeyMouse::Key(VirtualKeyCode::F3),
|
|
|
|
fullscreen: KeyMouse::Key(VirtualKeyCode::F11),
|
|
|
|
screenshot: KeyMouse::Key(VirtualKeyCode::F4),
|
|
|
|
toggle_ingame_ui: KeyMouse::Key(VirtualKeyCode::F6),
|
2019-06-11 04:08:55 +00:00
|
|
|
roll: KeyMouse::Mouse(MouseButton::Middle),
|
2019-08-27 11:42:17 +00:00
|
|
|
respawn: KeyMouse::Mouse(MouseButton::Left),
|
2019-07-29 16:19:08 +00:00
|
|
|
interact: KeyMouse::Key(VirtualKeyCode::E),
|
2019-06-08 23:35:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-05 15:57:48 +00:00
|
|
|
/// `GameplaySettings` contains sensitivity and gameplay options.
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2019-06-08 23:35:23 +00:00
|
|
|
#[serde(default)]
|
2019-06-05 15:57:48 +00:00
|
|
|
pub struct GameplaySettings {
|
2019-06-06 17:42:13 +00:00
|
|
|
pub pan_sensitivity: u32,
|
|
|
|
pub zoom_sensitivity: u32,
|
2019-10-02 12:44:41 +00:00
|
|
|
pub zoom_inversion: bool,
|
2019-07-07 00:15:22 +00:00
|
|
|
pub crosshair_transp: f32,
|
2019-10-23 19:40:45 +00:00
|
|
|
pub chat_transp: f32,
|
2019-07-23 01:02:57 +00:00
|
|
|
pub crosshair_type: CrosshairType,
|
2019-10-23 19:40:45 +00:00
|
|
|
pub intro_show: Intro,
|
2019-08-18 18:07:21 +00:00
|
|
|
pub xp_bar: XpBar,
|
|
|
|
pub shortcut_numbers: ShortcutNumbers,
|
|
|
|
pub bar_numbers: BarNumbers,
|
2019-07-26 02:28:53 +00:00
|
|
|
pub ui_scale: ScaleMode,
|
2019-04-15 17:51:26 +00:00
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
impl Default for GameplaySettings {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
pan_sensitivity: 100,
|
|
|
|
zoom_sensitivity: 100,
|
2019-10-02 12:44:41 +00:00
|
|
|
zoom_inversion: false,
|
2019-07-07 00:15:22 +00:00
|
|
|
crosshair_transp: 0.6,
|
2019-10-23 19:40:45 +00:00
|
|
|
chat_transp: 0.4,
|
2019-07-23 01:02:57 +00:00
|
|
|
crosshair_type: CrosshairType::Round,
|
2019-10-23 19:40:45 +00:00
|
|
|
intro_show: Intro::Show,
|
2019-08-18 18:07:21 +00:00
|
|
|
xp_bar: XpBar::OnGain,
|
|
|
|
shortcut_numbers: ShortcutNumbers::On,
|
|
|
|
bar_numbers: BarNumbers::Off,
|
2019-07-26 02:28:53 +00:00
|
|
|
ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
|
2019-06-08 23:35:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `NetworkingSettings` stores server and networking settings.
|
2019-04-18 17:40:29 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2019-06-08 23:35:23 +00:00
|
|
|
#[serde(default)]
|
2019-04-18 17:40:29 +00:00
|
|
|
pub struct NetworkingSettings {
|
|
|
|
pub username: String,
|
2019-08-07 19:42:44 +00:00
|
|
|
pub password: String,
|
2019-04-18 17:40:29 +00:00
|
|
|
pub servers: Vec<String>,
|
|
|
|
pub default_server: usize,
|
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
impl Default for NetworkingSettings {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
username: "Username".to_string(),
|
2019-08-07 19:42:44 +00:00
|
|
|
password: String::default(),
|
2019-07-20 11:59:35 +00:00
|
|
|
servers: vec!["server.veloren.net".to_string()],
|
2019-06-08 23:35:23 +00:00
|
|
|
default_server: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `Log` stores the name to the log file.
|
2019-04-25 11:49:36 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2019-06-08 23:35:23 +00:00
|
|
|
#[serde(default)]
|
2019-04-25 11:49:36 +00:00
|
|
|
pub struct Log {
|
|
|
|
pub file: PathBuf,
|
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
impl Default for Log {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
file: "voxygen.log".into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-06 19:11:39 +00:00
|
|
|
/// `GraphicsSettings` contains settings related to framerate and in-game visuals.
|
2019-05-20 17:40:35 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2019-06-08 23:35:23 +00:00
|
|
|
#[serde(default)]
|
2019-05-20 17:40:35 +00:00
|
|
|
pub struct GraphicsSettings {
|
|
|
|
pub view_distance: u32,
|
2019-06-06 19:11:39 +00:00
|
|
|
pub max_fps: u32,
|
2019-08-05 16:47:07 +00:00
|
|
|
pub fov: u16,
|
2019-09-26 07:28:40 +00:00
|
|
|
pub aa_mode: AaMode,
|
2019-05-20 17:40:35 +00:00
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
impl Default for GraphicsSettings {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
view_distance: 5,
|
|
|
|
max_fps: 60,
|
2019-08-05 16:47:07 +00:00
|
|
|
fov: 75,
|
2019-09-26 07:28:40 +00:00
|
|
|
aa_mode: AaMode::Fxaa,
|
2019-06-08 23:35:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-06 19:11:39 +00:00
|
|
|
/// `AudioSettings` controls the volume of different audio subsystems and which
|
2019-05-22 11:29:38 +00:00
|
|
|
/// device is used.
|
2019-05-20 16:54:54 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2019-06-08 23:35:23 +00:00
|
|
|
#[serde(default)]
|
2019-05-20 16:54:54 +00:00
|
|
|
pub struct AudioSettings {
|
2019-07-02 04:10:55 +00:00
|
|
|
pub master_volume: f32,
|
2019-05-20 16:54:54 +00:00
|
|
|
pub music_volume: f32,
|
|
|
|
pub sfx_volume: f32,
|
|
|
|
|
2019-05-22 11:29:38 +00:00
|
|
|
/// Audio Device that Voxygen will use to play audio.
|
|
|
|
pub audio_device: Option<String>,
|
2019-07-03 19:13:38 +00:00
|
|
|
pub audio_on: bool,
|
2019-05-20 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
impl Default for AudioSettings {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
2019-07-02 04:10:55 +00:00
|
|
|
master_volume: 1.0,
|
2019-09-01 19:04:03 +00:00
|
|
|
music_volume: 0.4,
|
|
|
|
sfx_volume: 0.6,
|
2019-06-08 23:35:23 +00:00
|
|
|
audio_device: None,
|
2019-09-25 09:09:45 +00:00
|
|
|
audio_on: true,
|
2019-06-08 23:35:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `Settings` contains everything that can be configured in the settings.ron file.
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(default)]
|
|
|
|
pub struct Settings {
|
|
|
|
pub controls: ControlSettings,
|
|
|
|
pub gameplay: GameplaySettings,
|
|
|
|
pub networking: NetworkingSettings,
|
|
|
|
pub log: Log,
|
|
|
|
pub graphics: GraphicsSettings,
|
|
|
|
pub audio: AudioSettings,
|
|
|
|
pub show_disclaimer: bool,
|
2019-07-18 22:50:46 +00:00
|
|
|
pub send_logon_commands: bool,
|
|
|
|
// TODO: Remove at a later date, for dev testing
|
|
|
|
pub logon_commands: Vec<String>,
|
2019-06-08 23:35:23 +00:00
|
|
|
}
|
|
|
|
|
2019-04-16 17:41:39 +00:00
|
|
|
impl Default for Settings {
|
|
|
|
fn default() -> Self {
|
2019-04-16 08:56:47 +00:00
|
|
|
Settings {
|
2019-06-08 23:35:23 +00:00
|
|
|
controls: ControlSettings::default(),
|
|
|
|
gameplay: GameplaySettings::default(),
|
|
|
|
networking: NetworkingSettings::default(),
|
|
|
|
log: Log::default(),
|
|
|
|
graphics: GraphicsSettings::default(),
|
|
|
|
audio: AudioSettings::default(),
|
2019-05-26 20:42:45 +00:00
|
|
|
show_disclaimer: true,
|
2019-07-18 22:50:46 +00:00
|
|
|
send_logon_commands: false,
|
|
|
|
logon_commands: Vec::new(),
|
2019-04-16 08:56:47 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-16 17:41:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Settings {
|
2019-05-17 07:55:51 +00:00
|
|
|
pub fn load() -> Self {
|
2019-04-25 16:24:00 +00:00
|
|
|
let path = Settings::get_settings_path();
|
2019-08-11 19:18:18 +00:00
|
|
|
|
2019-08-11 04:02:49 +00:00
|
|
|
if let Ok(file) = fs::File::open(&path) {
|
|
|
|
match ron::de::from_reader(file) {
|
2019-09-13 03:37:28 +00:00
|
|
|
Ok(s) => return s,
|
2019-08-11 04:02:49 +00:00
|
|
|
Err(e) => {
|
|
|
|
log::warn!("Failed to parse setting file! Fallback to default. {}", e);
|
|
|
|
// Rename the corrupted settings file
|
|
|
|
let mut new_path = path.to_owned();
|
|
|
|
new_path.pop();
|
|
|
|
new_path.push("settings.invalid.ron");
|
|
|
|
if let Err(err) = std::fs::rename(path, new_path) {
|
|
|
|
log::warn!("Failed to rename settings file. {}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-17 07:55:51 +00:00
|
|
|
}
|
2019-09-13 03:37:28 +00:00
|
|
|
// This is reached if either:
|
|
|
|
// - The file can't be opened (presumably it doesn't exist)
|
|
|
|
// - Or there was an error parsing the file
|
2019-08-11 04:02:49 +00:00
|
|
|
let default_settings = Self::default();
|
|
|
|
default_settings.save_to_file_warn();
|
|
|
|
default_settings
|
2019-04-15 17:51:26 +00:00
|
|
|
}
|
2019-04-16 16:06:23 +00:00
|
|
|
|
2019-07-26 02:28:53 +00:00
|
|
|
pub fn save_to_file_warn(&self) {
|
|
|
|
if let Err(err) = self.save_to_file() {
|
|
|
|
warn!("Failed to save settings: {:?}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-16 16:06:23 +00:00
|
|
|
pub fn save_to_file(&self) -> std::io::Result<()> {
|
2019-04-25 16:24:00 +00:00
|
|
|
let path = Settings::get_settings_path();
|
2019-05-20 21:32:16 +00:00
|
|
|
if let Some(dir) = path.parent() {
|
|
|
|
fs::create_dir_all(dir)?;
|
|
|
|
}
|
|
|
|
let mut config_file = fs::File::create(path)?;
|
2019-06-08 23:35:23 +00:00
|
|
|
|
2019-05-26 09:21:51 +00:00
|
|
|
let s: &str = &ron::ser::to_string_pretty(self, ron::ser::PrettyConfig::default()).unwrap();
|
2019-04-16 16:06:23 +00:00
|
|
|
config_file.write_all(s.as_bytes()).unwrap();
|
|
|
|
Ok(())
|
|
|
|
}
|
2019-04-25 16:24:00 +00:00
|
|
|
|
|
|
|
fn get_settings_path() -> PathBuf {
|
2019-10-22 13:53:05 +00:00
|
|
|
if let Some(val) = std::env::var_os("VOXYGEN_CONFIG") {
|
|
|
|
let settings = PathBuf::from(val).join("settings.ron");
|
|
|
|
if settings.exists() || settings.parent().map(|x| x.exists()).unwrap_or(false) {
|
|
|
|
return settings;
|
|
|
|
}
|
|
|
|
log::warn!("VOXYGEN_CONFIG points to invalid path.");
|
|
|
|
}
|
|
|
|
|
2019-06-08 23:35:23 +00:00
|
|
|
let proj_dirs = ProjectDirs::from("net", "veloren", "voxygen")
|
|
|
|
.expect("System's $HOME directory path not found!");
|
|
|
|
proj_dirs
|
|
|
|
.config_dir()
|
|
|
|
.join("settings")
|
|
|
|
.with_extension("ron")
|
2019-04-25 16:24:00 +00:00
|
|
|
}
|
2019-04-15 17:51:26 +00:00
|
|
|
}
|