1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/// Returns the original function pointer.
///
/// This should only be used from the main game thread.
macro_rules! real {
    ($f:ident) => {
        FUNCTIONS.as_ref().unwrap().$f
    };
}

/// Returns a pointer from the POINTERS variable.
///
/// This should only be used from the main game thread.
macro_rules! ptr {
    ($f:ident) => {
        POINTERS.as_ref().unwrap().$f
    };
}

macro_rules! find {
    ($handle:expr, $symbol:tt) => {{
        *(&$handle.sym($symbol)
                  .context(concat!("couldn't find ", $symbol))? as *const _ as *const _)
    }};
}

/// Defines console commands.
///
/// Commands defined by this macro will be automatically added
/// to the console command list and registered in the game.
macro_rules! command {
    ($name:ident, $callback:expr) => {
        #[allow(non_camel_case_types)]
        pub struct $name;

        impl $name {
            // This will get called by the engine, in main game thread.
            unsafe extern "C" fn callback() {
                const F: &Fn(crate::engine::Engine) = &$callback;

                // We know this is the main game thread.
                let engine = crate::engine::Engine::new();

                F(engine);
            }
        }

        impl crate::command::Command for $name {
            fn name(&self) -> &'static [u8] {
                lazy_static! {
                    static ref NAME: ::std::ffi::CString =
                        { ::std::ffi::CString::new(stringify!($name)).unwrap() };
                }

                NAME.as_bytes_with_nul()
            }

            fn callback(&self) -> unsafe extern "C" fn() {
                Self::callback
            }
        }
    };
}

/// Defines console variables.
///
/// Variables defined by this macro will be automatically added
/// to the console command list and registered in the game.
macro_rules! cvar {
    ($name:ident, $default_value:expr) => {
        #[allow(non_upper_case_globals)]
        pub static $name: crate::cvar::CVar =
            crate::cvar::CVar { engine_cvar: {
                               static mut ENGINE_CVAR: crate::cvar::cvar_t = crate::cvar::EMPTY_CVAR_T;
                               unsafe { &ENGINE_CVAR as *const _ as *mut _ }
                           },
                           default_value: $default_value,
                           name: stringify!($name) };
    };
}