veloren_common_base/
lib.rs

1pub mod userdata_dir;
2
3pub use userdata_dir::userdata_dir;
4
5// Panic in debug or tests, warn in release
6#[macro_export]
7macro_rules! dev_panic {
8    ($msg:expr) => {
9        if cfg!(any(debug_assertions, test)) {
10            panic!("{}", $msg);
11        } else {
12            tracing::error!("{}", $msg);
13        }
14    };
15
16    ($msg:expr, or return $result:expr) => {
17        if cfg!(any(debug_assertions, test)) {
18            panic!("{}", $msg);
19        } else {
20            tracing::warn!("{}", $msg);
21            return $result;
22        }
23    };
24}
25
26#[cfg(feature = "tracy")]
27pub use profiling::tracy_client;
28
29/// Allows downstream crates to conditionally do things based on whether tracy
30/// is enabled without having to expose a cargo feature themselves.
31pub const TRACY_ENABLED: bool = cfg!(feature = "tracy");
32
33#[cfg(not(feature = "tracy"))]
34#[macro_export]
35macro_rules! plot {
36    ($name:expr, $value:expr) => {
37        // type check
38        let _: f64 = $value;
39    };
40}
41
42#[cfg(feature = "tracy")]
43pub use tracy_client::plot;
44
45// https://discordapp.com/channels/676678179678715904/676685797524766720/723358438943621151
46#[cfg(not(feature = "tracy"))]
47#[macro_export]
48macro_rules! span {
49    ($guard_name:tt, $level:ident, $name:expr, $($fields:tt)*) => {
50        let span = tracing::span!(tracing::Level::$level, $name, $($fields)*);
51        let $guard_name = span.enter();
52    };
53    ($guard_name:tt, $level:ident, $name:expr) => {
54        let span = tracing::span!(tracing::Level::$level, $name);
55        let $guard_name = span.enter();
56    };
57    ($guard_name:tt, $name:expr) => {
58        let span = tracing::span!(tracing::Level::TRACE, $name);
59        let $guard_name = span.enter();
60    };
61    ($guard_name:tt, $no_tracy_name:expr, $tracy_name:expr) => {
62        $crate::span!($guard_name, $no_tracy_name);
63    };
64}
65
66#[cfg(feature = "tracy")]
67#[macro_export]
68macro_rules! span {
69    ($guard_name:tt, $level:ident, $name:expr, $($fields:tt)*) => {
70        let span = tracing::span!(tracing::Level::$level, $name, $($fields)*);
71        let $guard_name = span.enter();
72    };
73    ($guard_name:tt, $level:ident, $name:expr) => {
74        let span = tracing::span!(tracing::Level::$level, $name);
75        let $guard_name = span.enter();
76    };
77    ($guard_name:tt, $name:expr) => {
78        // Directly use `tracy_client` to decrease overhead for better timing
79        $crate::prof_span_alloc!($guard_name, $name);
80    };
81    ($guard_name:tt, $no_tracy_name:expr, $tracy_name:expr) => {
82        $crate::span!($guard_name, $tracy_name);
83    };
84}
85
86#[cfg(not(feature = "tracy"))]
87pub struct ProfSpan;
88
89/// Just implemented so that we dont need to have
90/// #[expect(clippy::drop_non_drop)] everywhere
91#[cfg(not(feature = "tracy"))]
92impl Drop for ProfSpan {
93    fn drop(&mut self) {}
94}
95
96#[cfg(feature = "tracy")]
97pub struct ProfSpan(pub tracy_client::Span);
98
99/// Like the span macro but only used when profiling and not in regular tracing
100/// operations
101#[cfg(not(feature = "tracy"))]
102#[macro_export]
103macro_rules! prof_span {
104    ($guard_name:tt, $name:expr) => {
105        let $guard_name = $crate::ProfSpan;
106    };
107    // Shorthand for when you want the guard to just be dropped at the end of the scope instead
108    // of controlling it manually
109    ($name:expr) => {
110        $crate::prof_span!(_guard, $name);
111    };
112}
113
114/// Like the span macro but only used when profiling and not in regular tracing
115/// operations
116#[cfg(feature = "tracy")]
117#[macro_export]
118macro_rules! prof_span {
119    ($guard_name:tt, $name:expr) => {
120        let $guard_name = $crate::ProfSpan(
121            // No callstack since this has significant overhead
122            $crate::tracy_client::span!($name, 0),
123        );
124    };
125    // Shorthand for when you want the guard to just be dropped at the end of the scope instead
126    // of controlling it manually
127    ($name:expr) => {
128        $crate::prof_span!(_guard, $name);
129    };
130}
131
132/// Like the prof_span macro but this one allocates so it can use strings only
133/// known at runtime.
134#[cfg(not(feature = "tracy"))]
135#[macro_export]
136macro_rules! prof_span_alloc {
137    ($guard_name:tt, $name:expr) => {
138        let $guard_name = $crate::ProfSpan;
139    };
140    // Shorthand for when you want the guard to just be dropped at the end of the scope instead
141    // of controlling it manually
142    ($name:expr) => {
143        $crate::prof_span!(_guard, $name);
144    };
145}
146
147/// Like the prof_span macro but this one allocates so it can use strings only
148/// known at runtime.
149#[cfg(feature = "tracy")]
150#[macro_export]
151macro_rules! prof_span_alloc {
152    ($guard_name:tt, $name:expr) => {
153        let $guard_name = $crate::ProfSpan({
154            struct S;
155            let type_name = core::any::type_name::<S>();
156            let function_name = &type_name[..type_name.len() - 3];
157            $crate::tracy_client::Client::running()
158                .expect("prof_span_alloc! without a running tracy_client::Client")
159                // No callstack since this has significant overhead
160                .span_alloc(Some($name), function_name, file!(), line!(), 0)
161        });
162    };
163    // Shorthand for when you want the guard to just be dropped at the end of the scope instead
164    // of controlling it manually
165    ($name:expr) => {
166        $crate::prof_span!(_guard, $name);
167    };
168}