veloren/voxygen/src/main.rs

205 lines
7.0 KiB
Rust
Raw Normal View History

2019-08-19 12:39:23 +00:00
#![deny(unsafe_code)]
#![allow(clippy::option_map_unit_fn)]
#![feature(bool_to_option)]
#![recursion_limit = "2048"]
2019-01-23 20:01:58 +00:00
use veloren_voxygen::{
2020-11-12 03:55:40 +00:00
audio::AudioFrontend,
i18n::{self, i18n_asset_key, Localization},
profile::Profile,
2020-02-08 03:26:17 +00:00
run,
scene::terrain::SpriteRenderContext,
settings::{get_fps, AudioOutput, Settings},
window::Window,
2020-02-08 03:26:17 +00:00
GlobalState,
2020-01-20 13:37:29 +00:00
};
use common::{
2020-12-12 22:14:24 +00:00
assets::{self, AssetExt},
clock::Clock,
};
2020-02-08 03:26:17 +00:00
use std::panic;
use tracing::{error, info, warn};
#[allow(clippy::manual_unwrap_or)]
fn main() {
// Load the settings
// 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
// whether we create a log file or not.
let mut settings = Settings::load();
// Save settings to add new fields or create the file if it is not already there
if let Err(err) = settings.save_to_file() {
panic!("Failed to save settings: {:?}", err);
}
// Init logging and hold the guards.
2021-03-28 23:40:53 +00:00
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
let default_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| {
let panic_info_payload = panic_info.payload();
let payload_string = panic_info_payload.downcast_ref::<String>();
let reason = match payload_string {
Some(s) => &s,
None => {
let payload_str = panic_info_payload.downcast_ref::<&str>();
match payload_str {
Some(st) => st,
None => "Payload is not a string",
}
},
};
let msg = format!(
"A critical error has occurred and Voxygen has been forced to \
terminate in an unusual manner. Details about the error can be \
found below.\n\
\n\
> What should I do?\n\
\n\
We need your help to fix this! You can help by contacting us and \
reporting this problem. To do this, open an issue on the Veloren \
issue tracker:\n\
\n\
https://www.gitlab.com/veloren/veloren/issues/new\n\
\n\
If you're on the Veloren community Discord server, we'd be \
grateful if you could also post a message in the #support channel.
\n\
> What should I include?\n\
\n\
The error information below will be useful in finding and fixing \
the problem. Please include as much information about your setup \
and the events that led up to the panic as possible.
\n\
Voxygen has logged information about the problem (including this \
message) to the file {}. Please include the contents of this \
file in your bug report.
\n\
> Error information\n\
\n\
The information below is intended for developers and testers.\n\
\n\
Panic Payload: {:?}\n\
PanicInfo: {}\n\
Game version: {} [{}]",
Settings::load()
.log
.logs_path
.join("voxygen-<date>.log")
.display(),
reason,
panic_info,
common::util::GIT_HASH.to_string(),
common::util::GIT_DATE.to_string()
);
error!(
"VOXYGEN HAS PANICKED\n\n{}\n\nBacktrace:\n{:?}",
msg,
backtrace::Backtrace::new(),
);
#[cfg(feature = "native-dialog")]
{
2021-02-07 05:48:57 +00:00
use native_dialog::{MessageDialog, MessageType};
let mbox = move || {
2021-02-07 05:48:57 +00:00
MessageDialog::new()
.set_title("Voxygen has panicked")
//somehow `<` and `>` are invalid characters and cause the msg to get replaced
// by some generic text thus i replace them
2021-02-07 05:48:57 +00:00
.set_text(&msg.replace('<', "[").replace('>', "]"))
.set_type(MessageType::Error)
.show_alert()
.unwrap()
};
// On windows we need to spawn a thread as the msg doesn't work otherwise
#[cfg(target_os = "windows")]
{
let builder = std::thread::Builder::new().name("shutdown".into());
builder
.spawn(move || {
mbox();
})
.unwrap()
.join()
.unwrap();
}
2020-09-09 10:11:56 +00:00
#[cfg(not(target_os = "windows"))]
mbox();
}
default_hook(panic_info);
}));
2020-12-12 22:14:24 +00:00
assets::start_hot_reloading();
2020-06-17 07:49:14 +00:00
// Initialise watcher for animation hotreloading
#[cfg(feature = "hot-anim")]
anim::init();
// Setup audio
2020-11-19 18:46:31 +00:00
let mut audio = match settings.audio.output {
AudioOutput::Off => AudioFrontend::no_audio(),
AudioOutput::Automatic => AudioFrontend::new(settings.audio.max_sfx_channels),
// AudioOutput::Device(ref dev) => Some(dev.clone()),
};
2021-04-18 18:05:27 +00:00
audio.set_master_volume(settings.audio.master_volume);
audio.set_music_volume(settings.audio.music_volume);
audio.set_sfx_volume(settings.audio.sfx_volume);
// Load the profile.
let profile = Profile::load();
2020-12-13 01:09:57 +00:00
let i18n = Localization::load(&i18n_asset_key(&settings.language.selected_language))
.unwrap_or_else(|error| {
let selected_language = &settings.language.selected_language;
warn!(
?error,
?selected_language,
"Impossible to load language: change to the default language (English) instead.",
);
settings.language.selected_language = i18n::REFERENCE_LANG.to_owned();
Localization::load_expect(&i18n_asset_key(&settings.language.selected_language))
});
2020-12-12 22:14:24 +00:00
i18n.read().log_missing_entries();
// Create window
let (mut window, event_loop) = Window::new(&settings).expect("Failed to create window!");
2020-12-02 00:35:32 +00:00
let clipboard = iced_winit::Clipboard::new(window.window());
let lazy_init = SpriteRenderContext::new(window.renderer_mut());
let global_state = GlobalState {
audio,
profile,
window,
lazy_init,
clock: Clock::new(std::time::Duration::from_secs_f64(
1.0 / get_fps(settings.graphics.max_fps) as f64,
)),
settings,
info_message: None,
#[cfg(feature = "singleplayer")]
singleplayer: None,
2020-12-12 22:14:24 +00:00
i18n,
2020-12-02 00:35:32 +00:00
clipboard,
client_error: None,
};
2019-06-19 19:25:08 +00:00
run::run(global_state, event_loop);
}