arcdps\globals/
arc.rs

1use crate::{
2    exports::raw::{
3        Export0, Export3, Export5, Export6, Export7, Export8, Export9, Export10,
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    unsafe { 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        unsafe {
69            Self {
70                handle,
71                version,
72                e0: transmute(exported_proc(handle, "e0\0")),
73                e3: transmute(exported_proc(handle, "e3\0")),
74                e5: transmute(exported_proc(handle, "e5\0")),
75                e6: transmute(exported_proc(handle, "e6\0")),
76                e7: transmute(exported_proc(handle, "e7\0")),
77                e8: transmute(exported_proc(handle, "e8\0")),
78                e9: transmute(exported_proc(handle, "e9\0")),
79                e10: transmute(exported_proc(handle, "e10\0")),
80                add_extension: transmute(exported_proc(handle, "addextension2\0")),
81                free_extension: transmute(exported_proc(handle, "freeextension2\0")),
82                list_extension: transmute(exported_proc(handle, "listextension\0")),
83            }
84        }
85    }
86
87    /// Initializes the ArcDPS globals.
88    pub unsafe fn init(handle: HMODULE, version: Option<&'static str>) -> &'static Self {
89        ARC_GLOBALS.get_or_init(|| unsafe { Self::new(handle, version) })
90    }
91
92    /// Returns the ArcDPS globals.
93    #[inline]
94    pub fn get() -> &'static Self {
95        Self::try_get().expect("arcdps globals not initialized")
96    }
97
98    /// Tries to retrieve the ArcDPS globals.
99    #[inline]
100    pub fn try_get() -> Option<&'static Self> {
101        ARC_GLOBALS.get()
102    }
103}
104
105unsafe impl Send for ArcGlobals {}
106
107unsafe impl Sync for ArcGlobals {}