arcdps\extras/
globals.rs

1//! Global instance with Unofficial Extras information.
2
3use crate::{
4    extras::exports::raw::{ExportGetKey, ExportGetKeybind},
5    util::exported_proc,
6};
7use std::{mem::transmute, sync::OnceLock};
8use windows::Win32::Foundation::HMODULE;
9
10/// Global instance of Unofficial Extras handle & exported functions.
11pub static EXTRAS_GLOBALS: OnceLock<ExtrasGlobals> = OnceLock::new();
12
13/// Unofficial Extras handle & exported functions.
14pub struct ExtrasGlobals {
15    /// Handle to Unofficial Extras dll.
16    pub handle: HMODULE,
17
18    /// Unofficial Extras version as string.
19    pub version: Option<&'static str>,
20
21    /// Get key export.
22    pub get_key: Option<ExportGetKey>,
23
24    /// Get key bind export.
25    pub get_keybind: Option<ExportGetKeybind>,
26}
27
28impl ExtrasGlobals {
29    /// Creates new Unofficial Extras globals.
30    pub unsafe fn new(handle: HMODULE, version: Option<&'static str>) -> Self {
31        #![allow(clippy::missing_transmute_annotations)]
32        Self {
33            handle,
34            version,
35            get_key: transmute(exported_proc(handle, "get_key\0")),
36            get_keybind: transmute(exported_proc(handle, "get_key_bind\0")),
37        }
38    }
39
40    /// Initializes the Unofficial Extras globals.
41    pub unsafe fn init(handle: HMODULE, version: Option<&'static str>) -> &'static Self {
42        EXTRAS_GLOBALS.get_or_init(|| Self::new(handle, version))
43    }
44
45    /// Returns the Unofficial Extras globals.
46    #[inline]
47    pub fn get() -> &'static Self {
48        Self::try_get().expect("unofficial extras globals not initialized")
49    }
50
51    /// Tries to retrieve the Unofficial Extras globals.
52    #[inline]
53    pub fn try_get() -> Option<&'static Self> {
54        EXTRAS_GLOBALS.get()
55    }
56}
57
58unsafe impl Send for ExtrasGlobals {}
59
60unsafe impl Sync for ExtrasGlobals {}