mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'imbris/voxygen-settings-improvements' into 'master'
Cleanup things in voxygen settings, making the directory externally specified, removing unused and planned to be removed things Closes #853 See merge request veloren/veloren!2645
This commit is contained in:
commit
b8b27cb5f7
@ -3436,12 +3436,16 @@ impl Hud {
|
|||||||
.clamped(1.25, max_zoom / 64.0);
|
.clamped(1.25, max_zoom / 64.0);
|
||||||
|
|
||||||
global_state.settings.interface.map_zoom = new_zoom_lvl;
|
global_state.settings.interface.map_zoom = new_zoom_lvl;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
} else if global_state.settings.interface.minimap_show {
|
} else if global_state.settings.interface.minimap_show {
|
||||||
let new_zoom_lvl = global_state.settings.interface.minimap_zoom * factor;
|
let new_zoom_lvl = global_state.settings.interface.minimap_zoom * factor;
|
||||||
|
|
||||||
global_state.settings.interface.minimap_zoom = new_zoom_lvl;
|
global_state.settings.interface.minimap_zoom = new_zoom_lvl;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
show.map && global_state.settings.interface.minimap_show
|
show.map && global_state.settings.interface.minimap_show
|
||||||
|
@ -50,9 +50,12 @@ use crate::{
|
|||||||
use common::clock::Clock;
|
use common::clock::Clock;
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
use i18n::LocalizationHandle;
|
use i18n::LocalizationHandle;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// A type used to store state that is shared between all play states.
|
/// A type used to store state that is shared between all play states.
|
||||||
pub struct GlobalState {
|
pub struct GlobalState {
|
||||||
|
pub userdata_dir: PathBuf,
|
||||||
|
pub config_dir: PathBuf,
|
||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
pub profile: Profile,
|
pub profile: Profile,
|
||||||
pub window: Window,
|
pub window: Window,
|
||||||
|
@ -17,33 +17,54 @@ use veloren_voxygen::{
|
|||||||
#[cfg(feature = "hot-reloading")]
|
#[cfg(feature = "hot-reloading")]
|
||||||
use common::assets;
|
use common::assets;
|
||||||
use common::clock::Clock;
|
use common::clock::Clock;
|
||||||
use std::panic;
|
use std::{panic, path::PathBuf};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
#[cfg(feature = "egui-ui")]
|
#[cfg(feature = "egui-ui")]
|
||||||
use veloren_voxygen::ui::egui::EguiState;
|
use veloren_voxygen::ui::egui::EguiState;
|
||||||
|
|
||||||
#[allow(clippy::manual_unwrap_or)]
|
#[allow(clippy::manual_unwrap_or)]
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let userdata_dir = common_base::userdata_dir_workspace!();
|
||||||
|
|
||||||
|
// Determine where Voxygen's logs should go
|
||||||
|
// Choose a path to store the logs by the following order:
|
||||||
|
// - The VOXYGEN_LOGS environment variable
|
||||||
|
// - The <userdata>/voxygen/logs
|
||||||
|
let logs_dir = std::env::var_os("VOXYGEN_LOGS")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.unwrap_or_else(|| userdata_dir.join("voxygen").join("logs"));
|
||||||
|
|
||||||
|
// Init logging and hold the guards.
|
||||||
|
const LOG_FILENAME: &str = "voxygen.log";
|
||||||
|
let _guards = common_frontend::init_stdout(Some((&logs_dir, LOG_FILENAME)));
|
||||||
|
|
||||||
|
info!("Using userdata dir at: {}", userdata_dir.display());
|
||||||
|
|
||||||
|
// Determine Voxygen's config directory either by env var or placed in veloren's
|
||||||
|
// userdata folder
|
||||||
|
let config_dir = std::env::var_os("VOXYGEN_CONFIG")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.and_then(|path| {
|
||||||
|
if path.exists() {
|
||||||
|
Some(path)
|
||||||
|
} else {
|
||||||
|
warn!(?path, "VOXYGEN_CONFIG points to invalid path.");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| userdata_dir.join("voxygen"));
|
||||||
|
info!("Using config dir at: {}", config_dir.display());
|
||||||
|
|
||||||
// Load the settings
|
// Load the settings
|
||||||
// Note: This won't log anything due to it being called before
|
// Note: This won't log anything due to it being called before
|
||||||
// `logging::init`. The issue is we need to read a setting to decide
|
// `logging::init`. The issue is we need to read a setting to decide
|
||||||
// whether we create a log file or not.
|
// whether we create a log file or not.
|
||||||
let mut settings = Settings::load();
|
let mut settings = Settings::load(&config_dir);
|
||||||
// Save settings to add new fields or create the file if it is not already there
|
// Save settings to add new fields or create the file if it is not already there
|
||||||
if let Err(err) = settings.save_to_file() {
|
if let Err(err) = settings.save_to_file(&config_dir) {
|
||||||
panic!("Failed to save settings: {:?}", err);
|
panic!("Failed to save settings: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init logging and hold the guards.
|
|
||||||
const LOG_FILENAME: &str = "voxygen.log";
|
|
||||||
let _guards = common_frontend::init_stdout(Some((&settings.log.logs_path, LOG_FILENAME)));
|
|
||||||
|
|
||||||
if let Some(path) = veloren_voxygen::settings::voxygen_data_dir().parent() {
|
|
||||||
info!("Using userdata dir at: {}", path.display());
|
|
||||||
} else {
|
|
||||||
error!("Can't log userdata dir, voxygen data dir has no parent!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up panic handler to relay swish panic messages to the user
|
// Set up panic handler to relay swish panic messages to the user
|
||||||
let default_hook = panic::take_hook();
|
let default_hook = panic::take_hook();
|
||||||
panic::set_hook(Box::new(move |panic_info| {
|
panic::set_hook(Box::new(move |panic_info| {
|
||||||
@ -92,9 +113,7 @@ fn main() {
|
|||||||
Panic Payload: {:?}\n\
|
Panic Payload: {:?}\n\
|
||||||
PanicInfo: {}\n\
|
PanicInfo: {}\n\
|
||||||
Game version: {} [{}]",
|
Game version: {} [{}]",
|
||||||
Settings::load()
|
logs_dir
|
||||||
.log
|
|
||||||
.logs_path
|
|
||||||
.join("voxygen-<date>.log")
|
.join("voxygen-<date>.log")
|
||||||
.display(),
|
.display(),
|
||||||
reason,
|
reason,
|
||||||
@ -171,7 +190,7 @@ fn main() {
|
|||||||
audio.set_sfx_volume(settings.audio.sfx_volume);
|
audio.set_sfx_volume(settings.audio.sfx_volume);
|
||||||
|
|
||||||
// Load the profile.
|
// Load the profile.
|
||||||
let profile = Profile::load();
|
let profile = Profile::load(&config_dir);
|
||||||
|
|
||||||
let mut i18n =
|
let mut i18n =
|
||||||
LocalizationHandle::load(&settings.language.selected_language).unwrap_or_else(|error| {
|
LocalizationHandle::load(&settings.language.selected_language).unwrap_or_else(|error| {
|
||||||
@ -198,6 +217,8 @@ fn main() {
|
|||||||
let egui_state = EguiState::new(&window);
|
let egui_state = EguiState::new(&window);
|
||||||
|
|
||||||
let global_state = GlobalState {
|
let global_state = GlobalState {
|
||||||
|
userdata_dir,
|
||||||
|
config_dir,
|
||||||
audio,
|
audio,
|
||||||
profile,
|
profile,
|
||||||
window,
|
window,
|
||||||
|
@ -139,7 +139,9 @@ impl PlayState for CharSelectionState {
|
|||||||
global_state
|
global_state
|
||||||
.profile
|
.profile
|
||||||
.set_selected_character(server_name, selected);
|
.set_selected_character(server_name, selected);
|
||||||
global_state.profile.save_to_file_warn();
|
global_state
|
||||||
|
.profile
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,7 +187,9 @@ impl PlayState for CharSelectionState {
|
|||||||
match event {
|
match event {
|
||||||
client::Event::SetViewDistance(vd) => {
|
client::Event::SetViewDistance(vd) => {
|
||||||
global_state.settings.graphics.view_distance = vd;
|
global_state.settings.graphics.view_distance = vd;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
},
|
},
|
||||||
client::Event::Disconnect => {
|
client::Event::Disconnect => {
|
||||||
global_state.info_message = Some(
|
global_state.info_message = Some(
|
||||||
|
@ -175,7 +175,9 @@ impl PlayState for MainMenuState {
|
|||||||
match event {
|
match event {
|
||||||
client::Event::SetViewDistance(vd) => {
|
client::Event::SetViewDistance(vd) => {
|
||||||
global_state.settings.graphics.view_distance = vd;
|
global_state.settings.graphics.view_distance = vd;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
},
|
},
|
||||||
client::Event::Disconnect => {
|
client::Event::Disconnect => {
|
||||||
global_state.info_message = Some(
|
global_state.info_message = Some(
|
||||||
@ -238,7 +240,9 @@ impl PlayState for MainMenuState {
|
|||||||
if !net_settings.servers.contains(&server_address) {
|
if !net_settings.servers.contains(&server_address) {
|
||||||
net_settings.servers.push(server_address.clone());
|
net_settings.servers.push(server_address.clone());
|
||||||
}
|
}
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
|
|
||||||
let connection_args = if use_quic {
|
let connection_args = if use_quic {
|
||||||
ConnectionArgs::Quic {
|
ConnectionArgs::Quic {
|
||||||
@ -302,7 +306,9 @@ impl PlayState for MainMenuState {
|
|||||||
.networking
|
.networking
|
||||||
.trusted_auth_servers
|
.trusted_auth_servers
|
||||||
.insert(auth_server.clone());
|
.insert(auth_server.clone());
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
}
|
}
|
||||||
self.init
|
self.init
|
||||||
.client()
|
.client()
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
use common::comp;
|
|
||||||
use directories::ProjectDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{fs, io::Write, path::PathBuf};
|
|
||||||
use tracing::warn;
|
|
||||||
|
|
||||||
const VALID_VERSION: u32 = 0; // Change this if you broke charsaves
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct CharacterData {
|
|
||||||
pub name: String,
|
|
||||||
pub body: comp::Body,
|
|
||||||
pub tool: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
|
||||||
//#[serde(default)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Meta {
|
|
||||||
pub characters: Vec<CharacterData>,
|
|
||||||
pub selected_character: usize,
|
|
||||||
pub version: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Meta {
|
|
||||||
pub fn delete_character(&mut self, index: usize) {
|
|
||||||
self.characters.remove(index);
|
|
||||||
if index < self.selected_character {
|
|
||||||
self.selected_character -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_character(&mut self, data: CharacterData) -> usize {
|
|
||||||
self.characters.push(data);
|
|
||||||
// return new character's index
|
|
||||||
self.characters.len() - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load() -> Self {
|
|
||||||
let path = Self::get_meta_path();
|
|
||||||
|
|
||||||
if let Ok(file) = fs::File::open(&path) {
|
|
||||||
match ron::de::from_reader::<_, Meta>(file) {
|
|
||||||
Ok(s) => {
|
|
||||||
if s.version == VALID_VERSION {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
warn!(?e, ?file, "Failed to parse meta file! Fallback to default");
|
|
||||||
// Rename the corrupted settings file
|
|
||||||
let mut new_path = path.to_owned();
|
|
||||||
new_path.pop();
|
|
||||||
new_path.push("meta.invalid.ron");
|
|
||||||
if let Err(e) = std::fs::rename(path.clone(), new_path.clone()) {
|
|
||||||
warn!(?e, ?path, ?new_path, "Failed to rename meta file");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// This is reached if either:
|
|
||||||
// - The file can't be opened (presumably it doesn't exist)
|
|
||||||
// - Or there was an error parsing the file
|
|
||||||
let default = Self::default();
|
|
||||||
default.save_to_file_warn();
|
|
||||||
default
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save_to_file_warn(&self) {
|
|
||||||
if let Err(err) = self.save_to_file() {
|
|
||||||
warn!(?e, "Failed to save settings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save_to_file(&self) -> std::io::Result<()> {
|
|
||||||
let path = Self::get_meta_path();
|
|
||||||
if let Some(dir) = path.parent() {
|
|
||||||
fs::create_dir_all(dir)?;
|
|
||||||
}
|
|
||||||
let mut meta_file = fs::File::create(path)?;
|
|
||||||
|
|
||||||
let s: &str = &ron::ser::to_string_pretty(self, ron::ser::PrettyConfig::default()).unwrap();
|
|
||||||
meta_file.write_all(s.as_bytes()).unwrap();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_meta_path() -> PathBuf {
|
|
||||||
if let Some(path) = std::env::var_os("VOXYGEN_CONFIG") {
|
|
||||||
let meta = PathBuf::from(path).join("meta.ron");
|
|
||||||
if meta.exists() || meta.parent().map(|x| x.exists()).unwrap_or(false) {
|
|
||||||
return meta;
|
|
||||||
}
|
|
||||||
warn!(?path, "VOXYGEN_CONFIG points to invalid path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let proj_dirs = ProjectDirs::from("net", "veloren", "voxygen")
|
|
||||||
.expect("System's $HOME directory path not found!");
|
|
||||||
proj_dirs.config_dir().join("meta").with_extension("ron")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,12 @@
|
|||||||
use crate::{hud, settings};
|
use crate::hud;
|
||||||
use common::{character::CharacterId, comp::slot::InvSlotId};
|
use common::{character::CharacterId, comp::slot::InvSlotId};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{fs, io::Write, path::PathBuf};
|
use std::{
|
||||||
|
fs,
|
||||||
|
io::Write,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
/// Represents a character in the profile.
|
/// Represents a character in the profile.
|
||||||
@ -76,8 +80,8 @@ impl Default for Profile {
|
|||||||
|
|
||||||
impl Profile {
|
impl Profile {
|
||||||
/// Load the profile.ron file from the standard path or create it.
|
/// Load the profile.ron file from the standard path or create it.
|
||||||
pub fn load() -> Self {
|
pub fn load(config_dir: &Path) -> Self {
|
||||||
let path = Profile::get_path();
|
let path = Profile::get_path(config_dir);
|
||||||
|
|
||||||
if let Ok(file) = fs::File::open(&path) {
|
if let Ok(file) = fs::File::open(&path) {
|
||||||
match ron::de::from_reader(file) {
|
match ron::de::from_reader(file) {
|
||||||
@ -100,13 +104,13 @@ impl Profile {
|
|||||||
// - The file can't be opened (presumably it doesn't exist)
|
// - The file can't be opened (presumably it doesn't exist)
|
||||||
// - Or there was an error parsing the file
|
// - Or there was an error parsing the file
|
||||||
let default_profile = Self::default();
|
let default_profile = Self::default();
|
||||||
default_profile.save_to_file_warn();
|
default_profile.save_to_file_warn(config_dir);
|
||||||
default_profile
|
default_profile
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save the current profile to disk, warn on failure.
|
/// Save the current profile to disk, warn on failure.
|
||||||
pub fn save_to_file_warn(&self) {
|
pub fn save_to_file_warn(&self, config_dir: &Path) {
|
||||||
if let Err(e) = self.save_to_file() {
|
if let Err(e) = self.save_to_file(config_dir) {
|
||||||
warn!(?e, "Failed to save profile");
|
warn!(?e, "Failed to save profile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,8 +198,8 @@ impl Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Save the current profile to disk.
|
/// Save the current profile to disk.
|
||||||
fn save_to_file(&self) -> std::io::Result<()> {
|
fn save_to_file(&self, config_dir: &Path) -> std::io::Result<()> {
|
||||||
let path = Profile::get_path();
|
let path = Profile::get_path(config_dir);
|
||||||
if let Some(dir) = path.parent() {
|
if let Some(dir) = path.parent() {
|
||||||
fs::create_dir_all(dir)?;
|
fs::create_dir_all(dir)?;
|
||||||
}
|
}
|
||||||
@ -206,19 +210,7 @@ impl Profile {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_path() -> PathBuf {
|
fn get_path(config_dir: &Path) -> PathBuf { config_dir.join("profile.ron") }
|
||||||
if let Some(path) = std::env::var_os("VOXYGEN_CONFIG") {
|
|
||||||
let profile = PathBuf::from(path.clone()).join("profile.ron");
|
|
||||||
if profile.exists() || profile.parent().map(|x| x.exists()).unwrap_or(false) {
|
|
||||||
return profile;
|
|
||||||
}
|
|
||||||
warn!(?path, "VOXYGEN_CONFIG points to invalid path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut path = settings::voxygen_data_dir();
|
|
||||||
path.push("profile.ron");
|
|
||||||
path
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -83,8 +83,12 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) {
|
|||||||
},
|
},
|
||||||
winit::event::Event::LoopDestroyed => {
|
winit::event::Event::LoopDestroyed => {
|
||||||
// Save any unsaved changes to settings and profile
|
// Save any unsaved changes to settings and profile
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
global_state.profile.save_to_file_warn();
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
|
global_state
|
||||||
|
.profile
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@ -100,7 +104,7 @@ fn handle_main_events_cleared(
|
|||||||
// Screenshot / Fullscreen toggle
|
// Screenshot / Fullscreen toggle
|
||||||
global_state
|
global_state
|
||||||
.window
|
.window
|
||||||
.resolve_deduplicated_events(&mut global_state.settings);
|
.resolve_deduplicated_events(&mut global_state.settings, &global_state.config_dir);
|
||||||
// Run tick here
|
// Run tick here
|
||||||
|
|
||||||
// What's going on here?
|
// What's going on here?
|
||||||
|
@ -259,7 +259,9 @@ impl SessionState {
|
|||||||
},
|
},
|
||||||
client::Event::SetViewDistance(vd) => {
|
client::Event::SetViewDistance(vd) => {
|
||||||
global_state.settings.graphics.view_distance = vd;
|
global_state.settings.graphics.view_distance = vd;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state
|
||||||
|
.settings
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
},
|
},
|
||||||
client::Event::Outcome(outcome) => outcomes.push(outcome),
|
client::Event::Outcome(outcome) => outcomes.push(outcome),
|
||||||
client::Event::CharacterCreated(_) => {},
|
client::Event::CharacterCreated(_) => {},
|
||||||
@ -1305,7 +1307,9 @@ impl PlayState for SessionState {
|
|||||||
state.slots,
|
state.slots,
|
||||||
);
|
);
|
||||||
|
|
||||||
global_state.profile.save_to_file_warn();
|
global_state
|
||||||
|
.profile
|
||||||
|
.save_to_file_warn(&global_state.config_dir);
|
||||||
|
|
||||||
info!("Event! -> ChangedHotbarState")
|
info!("Event! -> ChangedHotbarState")
|
||||||
},
|
},
|
||||||
|
@ -202,7 +202,6 @@ impl SettingsChange {
|
|||||||
global_state.audio.set_sfx_volume(audio.sfx_volume);
|
global_state.audio.set_sfx_volume(audio.sfx_volume);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
settings.save_to_file_warn();
|
|
||||||
},
|
},
|
||||||
SettingsChange::Chat(chat_change) => {
|
SettingsChange::Chat(chat_change) => {
|
||||||
let chat_tabs = &mut settings.chat.chat_tabs;
|
let chat_tabs = &mut settings.chat.chat_tabs;
|
||||||
@ -242,7 +241,6 @@ impl SettingsChange {
|
|||||||
settings.chat = ChatSettings::default();
|
settings.chat = ChatSettings::default();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
settings.save_to_file_warn();
|
|
||||||
},
|
},
|
||||||
SettingsChange::Control(control_change) => match control_change {
|
SettingsChange::Control(control_change) => match control_change {
|
||||||
Control::ChangeBinding(game_input) => {
|
Control::ChangeBinding(game_input) => {
|
||||||
@ -250,7 +248,6 @@ impl SettingsChange {
|
|||||||
},
|
},
|
||||||
Control::ResetKeyBindings => {
|
Control::ResetKeyBindings => {
|
||||||
settings.controls = ControlSettings::default();
|
settings.controls = ControlSettings::default();
|
||||||
settings.save_to_file_warn();
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SettingsChange::Gamepad(gamepad_change) => match gamepad_change {},
|
SettingsChange::Gamepad(gamepad_change) => match gamepad_change {},
|
||||||
@ -323,7 +320,6 @@ impl SettingsChange {
|
|||||||
window.mouse_y_inversion = settings.gameplay.mouse_y_inversion;
|
window.mouse_y_inversion = settings.gameplay.mouse_y_inversion;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
settings.save_to_file_warn();
|
|
||||||
},
|
},
|
||||||
SettingsChange::Graphics(graphics_change) => {
|
SettingsChange::Graphics(graphics_change) => {
|
||||||
match graphics_change {
|
match graphics_change {
|
||||||
@ -423,7 +419,6 @@ impl SettingsChange {
|
|||||||
global_state.window.set_size(graphics.window_size.into());
|
global_state.window.set_size(graphics.window_size.into());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
settings.save_to_file_warn();
|
|
||||||
},
|
},
|
||||||
SettingsChange::Interface(interface_change) => {
|
SettingsChange::Interface(interface_change) => {
|
||||||
match interface_change {
|
match interface_change {
|
||||||
@ -534,7 +529,6 @@ impl SettingsChange {
|
|||||||
.set_scaling_mode(settings.interface.ui_scale);
|
.set_scaling_mode(settings.interface.ui_scale);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
settings.save_to_file_warn();
|
|
||||||
},
|
},
|
||||||
SettingsChange::Language(language_change) => match language_change {
|
SettingsChange::Language(language_change) => match language_change {
|
||||||
Language::ChangeLanguage(new_language) => {
|
Language::ChangeLanguage(new_language) => {
|
||||||
@ -556,5 +550,6 @@ impl SettingsChange {
|
|||||||
},
|
},
|
||||||
SettingsChange::Networking(networking_change) => match networking_change {},
|
SettingsChange::Networking(networking_change) => match networking_change {},
|
||||||
}
|
}
|
||||||
|
settings.save_to_file_warn(&global_state.config_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use directories_next::UserDirs;
|
use directories_next::UserDirs;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{fs, path::PathBuf};
|
use std::{
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
pub mod audio;
|
pub mod audio;
|
||||||
@ -23,40 +26,6 @@ pub use interface::InterfaceSettings;
|
|||||||
pub use language::LanguageSettings;
|
pub use language::LanguageSettings;
|
||||||
pub use networking::NetworkingSettings;
|
pub use networking::NetworkingSettings;
|
||||||
|
|
||||||
/// `Log` stores whether we should create a log file
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct Log {
|
|
||||||
// Whether to create a log file or not.
|
|
||||||
// Default is to create one.
|
|
||||||
pub log_to_file: bool,
|
|
||||||
// The path on which the logs will be stored
|
|
||||||
pub logs_path: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Log {
|
|
||||||
fn default() -> Self {
|
|
||||||
// Chooses a path to store the logs by the following order:
|
|
||||||
// - The VOXYGEN_LOGS environment variable
|
|
||||||
// - The ProjectsDirs data local directory
|
|
||||||
// This function is only called if there isn't already an entry in the settings
|
|
||||||
// file. However, the VOXYGEN_LOGS environment variable always overrides
|
|
||||||
// the log file path if set.
|
|
||||||
let logs_path = std::env::var_os("VOXYGEN_LOGS")
|
|
||||||
.map(PathBuf::from)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
let mut path = voxygen_data_dir();
|
|
||||||
path.push("logs");
|
|
||||||
path
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
|
||||||
log_to_file: true,
|
|
||||||
logs_path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Settings` contains everything that can be configured in the settings.ron
|
/// `Settings` contains everything that can be configured in the settings.ron
|
||||||
/// file.
|
/// file.
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
@ -67,7 +36,6 @@ pub struct Settings {
|
|||||||
pub interface: InterfaceSettings,
|
pub interface: InterfaceSettings,
|
||||||
pub gameplay: GameplaySettings,
|
pub gameplay: GameplaySettings,
|
||||||
pub networking: NetworkingSettings,
|
pub networking: NetworkingSettings,
|
||||||
pub log: Log,
|
|
||||||
pub graphics: GraphicsSettings,
|
pub graphics: GraphicsSettings,
|
||||||
pub audio: AudioSettings,
|
pub audio: AudioSettings,
|
||||||
pub show_disclaimer: bool,
|
pub show_disclaimer: bool,
|
||||||
@ -104,7 +72,6 @@ impl Default for Settings {
|
|||||||
interface: InterfaceSettings::default(),
|
interface: InterfaceSettings::default(),
|
||||||
gameplay: GameplaySettings::default(),
|
gameplay: GameplaySettings::default(),
|
||||||
networking: NetworkingSettings::default(),
|
networking: NetworkingSettings::default(),
|
||||||
log: Log::default(),
|
|
||||||
graphics: GraphicsSettings::default(),
|
graphics: GraphicsSettings::default(),
|
||||||
audio: AudioSettings::default(),
|
audio: AudioSettings::default(),
|
||||||
show_disclaimer: true,
|
show_disclaimer: true,
|
||||||
@ -118,25 +85,12 @@ impl Default for Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn load() -> Self {
|
pub fn load(config_dir: &Path) -> Self {
|
||||||
let path = Self::get_settings_path();
|
let path = Self::get_path(config_dir);
|
||||||
|
|
||||||
if let Ok(file) = fs::File::open(&path) {
|
if let Ok(file) = fs::File::open(&path) {
|
||||||
match ron::de::from_reader::<_, Self>(file) {
|
match ron::de::from_reader::<_, Self>(file) {
|
||||||
Ok(mut s) => {
|
Ok(s) => return s,
|
||||||
// Override the logs path if it is explicitly set using the VOXYGEN_LOGS
|
|
||||||
// environment variable. This is needed to support package managers that enforce
|
|
||||||
// strict application confinement (e.g. snap). In fact, the veloren snap package
|
|
||||||
// relies on this environment variable to be respected in
|
|
||||||
// order to communicate a path where the snap package is
|
|
||||||
// allowed to write to.
|
|
||||||
if let Some(logs_path_override) =
|
|
||||||
std::env::var_os("VOXYGEN_LOGS").map(PathBuf::from)
|
|
||||||
{
|
|
||||||
s.log.logs_path = logs_path_override;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
},
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(?e, "Failed to parse setting file! Fallback to default.");
|
warn!(?e, "Failed to parse setting file! Fallback to default.");
|
||||||
// Rename the corrupted settings file
|
// Rename the corrupted settings file
|
||||||
@ -153,18 +107,18 @@ impl Settings {
|
|||||||
// - The file can't be opened (presumably it doesn't exist)
|
// - The file can't be opened (presumably it doesn't exist)
|
||||||
// - Or there was an error parsing the file
|
// - Or there was an error parsing the file
|
||||||
let default_settings = Self::default();
|
let default_settings = Self::default();
|
||||||
default_settings.save_to_file_warn();
|
default_settings.save_to_file_warn(config_dir);
|
||||||
default_settings
|
default_settings
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_to_file_warn(&self) {
|
pub fn save_to_file_warn(&self, config_dir: &Path) {
|
||||||
if let Err(e) = self.save_to_file() {
|
if let Err(e) = self.save_to_file(config_dir) {
|
||||||
warn!(?e, "Failed to save settings");
|
warn!(?e, "Failed to save settings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_to_file(&self) -> std::io::Result<()> {
|
pub fn save_to_file(&self, config_dir: &Path) -> std::io::Result<()> {
|
||||||
let path = Self::get_settings_path();
|
let path = Self::get_path(config_dir);
|
||||||
if let Some(dir) = path.parent() {
|
if let Some(dir) = path.parent() {
|
||||||
fs::create_dir_all(dir)?;
|
fs::create_dir_all(dir)?;
|
||||||
}
|
}
|
||||||
@ -173,25 +127,5 @@ impl Settings {
|
|||||||
fs::write(path, ron.as_bytes())
|
fs::write(path, ron.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_settings_path() -> PathBuf {
|
fn get_path(config_dir: &Path) -> PathBuf { config_dir.join("settings.ron") }
|
||||||
if let Some(path) = std::env::var_os("VOXYGEN_CONFIG") {
|
|
||||||
let settings = PathBuf::from(&path).join("settings.ron");
|
|
||||||
if settings.exists() || settings.parent().map(|x| x.exists()).unwrap_or(false) {
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
warn!(?path, "VOXYGEN_CONFIG points to invalid path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut path = voxygen_data_dir();
|
|
||||||
path.push("settings.ron");
|
|
||||||
path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn voxygen_data_dir() -> PathBuf {
|
|
||||||
// Note: since voxygen is technically a lib we made need to lift this up to
|
|
||||||
// run.rs
|
|
||||||
let mut path = common_base::userdata_dir_workspace!();
|
|
||||||
path.push("voxygen");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
@ -703,7 +703,11 @@ impl Window {
|
|||||||
|
|
||||||
pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer }
|
pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer }
|
||||||
|
|
||||||
pub fn resolve_deduplicated_events(&mut self, settings: &mut Settings) {
|
pub fn resolve_deduplicated_events(
|
||||||
|
&mut self,
|
||||||
|
settings: &mut Settings,
|
||||||
|
config_dir: &std::path::Path,
|
||||||
|
) {
|
||||||
// Handle screenshots and toggling fullscreen
|
// Handle screenshots and toggling fullscreen
|
||||||
if self.take_screenshot {
|
if self.take_screenshot {
|
||||||
self.take_screenshot = false;
|
self.take_screenshot = false;
|
||||||
@ -711,7 +715,7 @@ impl Window {
|
|||||||
}
|
}
|
||||||
if self.toggle_fullscreen {
|
if self.toggle_fullscreen {
|
||||||
self.toggle_fullscreen = false;
|
self.toggle_fullscreen = false;
|
||||||
self.toggle_fullscreen(settings);
|
self.toggle_fullscreen(settings, config_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,7 +1174,7 @@ impl Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_fullscreen(&mut self, settings: &mut Settings) {
|
pub fn toggle_fullscreen(&mut self, settings: &mut Settings, config_dir: &std::path::Path) {
|
||||||
let fullscreen = FullScreenSettings {
|
let fullscreen = FullScreenSettings {
|
||||||
enabled: !self.is_fullscreen(),
|
enabled: !self.is_fullscreen(),
|
||||||
..settings.graphics.fullscreen
|
..settings.graphics.fullscreen
|
||||||
@ -1178,7 +1182,7 @@ impl Window {
|
|||||||
|
|
||||||
self.set_fullscreen_mode(fullscreen);
|
self.set_fullscreen_mode(fullscreen);
|
||||||
settings.graphics.fullscreen = fullscreen;
|
settings.graphics.fullscreen = fullscreen;
|
||||||
settings.save_to_file_warn();
|
settings.save_to_file_warn(config_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_fullscreen(&self) -> bool { self.fullscreen.enabled }
|
pub fn is_fullscreen(&self) -> bool { self.fullscreen.enabled }
|
||||||
|
Loading…
Reference in New Issue
Block a user