1#[cfg(test)]
11#[inline]
12pub fn register_panic_handler() {}
13
14#[cfg(not(test))]
16#[allow(clippy::missing_panics_doc)]
17pub fn register_panic_handler() {
18 use bevy::prelude::error;
19 use rfd::{MessageButtons, MessageDialog};
20 use std::fs::File;
21 use std::io::Write;
22 use std::path::PathBuf;
23 use sysinfo::System;
24
25 let default_hook = std::panic::take_hook();
26 std::panic::set_hook(Box::new(move |info| {
27 let path = std::env::current_dir()
28 .unwrap_or(PathBuf::from("."))
29 .join("crash_report.txt");
30 let message = if let Some(message) = info.payload().downcast_ref::<&'static str>() {
31 String::from(*message)
32 } else {
33 String::from("An unrecoverable error has occurred.")
34 };
35 let location = if let Some(location) = info.location() {
36 location.to_string()
37 } else {
38 String::from("Unknown location")
39 };
40
41 error!("An unrecoverable error has occurred: {:?}", info);
42 MessageDialog::new()
43 .set_level(rfd::MessageLevel::Error)
44 .set_title("Unrecoverable Error")
45 .set_buttons(MessageButtons::Ok)
46 .set_description(format!(
47 "An unrecoverable error has occurred, the editor will shut down.
48The error was: {message}
49
50Error occurred at: {location}
51
52A crash file will be generated at {}",
53 path.display()
54 ))
55 .show();
56
57 let system = System::new_all();
58 let os_version = System::long_os_version().unwrap_or(String::from("Unknown"));
59 let mut dump_file = File::create(path).expect("Failed to create dump file");
60 writeln!(dump_file, "--- DungeonRS Crash Report ---").unwrap();
61 writeln!(
62 dump_file,
63 "Please provide the contents of this file when creating a bug report."
64 )
65 .unwrap();
66 writeln!(dump_file).unwrap();
67 writeln!(dump_file).unwrap();
68 writeln!(dump_file, "Operating System: {os_version}").unwrap();
69 writeln!(
70 dump_file,
71 "Memory: {}/{}",
72 system.used_memory(),
73 system.total_memory()
74 )
75 .unwrap();
76
77 writeln!(
78 dump_file,
79 "CPU: {} Cores {}",
80 system.cpus().len(),
81 system.cpus()[0].brand()
82 )
83 .unwrap();
84 for cpu in system.cpus() {
85 writeln!(
86 dump_file,
87 "{}: {}Hz ({}) {}%",
88 cpu.name(),
89 cpu.frequency(),
90 cpu.brand(),
91 cpu.cpu_usage()
92 )
93 .unwrap();
94 }
95
96 writeln!(dump_file).unwrap();
97 writeln!(dump_file, "---").unwrap();
98 writeln!(dump_file, "Error: {message}").unwrap();
99 writeln!(dump_file, "Location: {location}").unwrap();
100 writeln!(dump_file, "---").unwrap();
101 writeln!(dump_file, "Raw: {info:?}").unwrap();
102
103 dump_file.sync_all().unwrap();
104 default_hook(info);
105 }));
106}