arcdps\globals/
arc.rs

1use crate::{
2    exports::raw::{
3        Export0, Export10, Export3, Export5, Export6, Export7, Export8, Export9,
4        ExportAddExtension, ExportFreeExtension, ExportListExtension,
5    },
6    util::{exported_proc, str_from_cstr},
7};
8use std::{ffi::c_char, mem::transmute, sync::OnceLock};
9use windows::Win32::Foundation::HMODULE;
10
11/// Initializes ArcDPS information.
12#[inline]
13pub unsafe fn init_arc(arc_handle: HMODULE, version: *const c_char) {
14    ArcGlobals::init(arc_handle, str_from_cstr(version));
15}
16
17/// Global instance of ArcDPS handle & exported functions.
18static ARC_GLOBALS: OnceLock<ArcGlobals> = OnceLock::new();
19
20/// ArcDPS handle & exported functions.
21// TODO: should we move other globals from codegen here? or move this to codegen?
22#[derive(Debug)]
23pub struct ArcGlobals {
24    /// Handle to ArcDPS dll.
25    pub handle: HMODULE,
26
27    /// ArcDPS version as string.
28    pub version: Option<&'static str>,
29
30    /// Config path export.
31    pub e0: Option<Export0>,
32
33    /// Log file export.
34    pub e3: Option<Export3>,
35
36    /// Colors export.
37    pub e5: Option<Export5>,
38
39    /// Ui settings export.
40    pub e6: Option<Export6>,
41
42    /// Modifiers export.
43    pub e7: Option<Export7>,
44
45    /// Log window export.
46    pub e8: Option<Export8>,
47
48    /// Add event export.
49    pub e9: Option<Export9>,
50
51    /// Add event combat/skill export.
52    pub e10: Option<Export10>,
53
54    /// Add extension export.
55    pub add_extension: Option<ExportAddExtension>,
56
57    /// Free extension export.
58    pub free_extension: Option<ExportFreeExtension>,
59
60    /// List extension export.
61    pub list_extension: Option<ExportListExtension>,
62}
63
64impl ArcGlobals {
65    /// Creates new ArcDPS globals.
66    pub unsafe fn new(handle: HMODULE, version: Option<&'static str>) -> Self {
67        #![allow(clippy::missing_transmute_annotations)]
68        Self {
69            handle,
70            version,
71            e0: transmute(exported_proc(handle, "e0\0")),
72            e3: transmute(exported_proc(handle, "e3\0")),
73            e5: transmute(exported_proc(handle, "e5\0")),
74            e6: transmute(exported_proc(handle, "e6\0")),
75            e7: transmute(exported_proc(handle, "e7\0")),
76            e8: transmute(exported_proc(handle, "e8\0")),
77            e9: transmute(exported_proc(handle, "e9\0")),
78            e10: transmute(exported_proc(handle, "e10\0")),
79            add_extension: transmute(exported_proc(handle, "addextension2\0")),
80            free_extension: transmute(exported_proc(handle, "freeextension2\0")),
81            list_extension: transmute(exported_proc(handle, "listextension\0")),
82        }
83    }
84
85    /// Initializes the ArcDPS globals.
86    pub unsafe fn init(handle: HMODULE, version: Option<&'static str>) -> &'static Self {
87        ARC_GLOBALS.get_or_init(|| Self::new(handle, version))
88    }
89
90    /// Returns the ArcDPS globals.
91    #[inline]
92    pub fn get() -> &'static Self {
93        Self::try_get().expect("arcdps globals not initialized")
94    }
95
96    /// Tries to retrieve the ArcDPS globals.
97    #[inline]
98    pub fn try_get() -> Option<&'static Self> {
99        ARC_GLOBALS.get()
100    }
101}
102
103unsafe impl Send for ArcGlobals {}
104
105unsafe impl Sync for ArcGlobals {}