1use std::{collections::HashSet, sync::atomic::AtomicBool};
2
3use crate::lua::{self, ffi};
4
5static GMOD_CLOSED: AtomicBool = AtomicBool::new(true);
6
7#[inline]
8pub fn is_closed() -> bool {
9 GMOD_CLOSED.load(std::sync::atomic::Ordering::Acquire)
10}
11
12#[inline]
13pub fn is_open() -> bool {
14 !is_closed()
15}
16
17pub struct OpenClose {
18 pub priority: i32, pub id: &'static str,
20 pub open: fn(&lua::State),
21 pub close: fn(&lua::State),
22}
23
24pub const fn new(
25 priority: i32,
26 id: &'static str,
27 open: fn(&lua::State),
28 close: fn(&lua::State),
29) -> OpenClose {
30 OpenClose {
31 priority,
32 id,
33 open,
34 close,
35 }
36}
37
38inventory::collect!(OpenClose);
39
40fn get_sorted_modules() -> Vec<&'static OpenClose> {
41 let mut modules: Vec<&OpenClose> = inventory::iter::<OpenClose>().collect();
42
43 let mut seen_ids = HashSet::new();
44 for module in &modules {
45 if !seen_ids.insert(module.id) {
46 panic!("Duplicate OpenClose ID: {}", module.id);
47 }
48 }
49
50 modules.sort_by_key(|m| (m.priority, m.id));
53
54 modules
55}
56
57#[allow(unused)]
58pub fn load_all(state: &lua::State) {
59 GMOD_CLOSED.store(false, std::sync::atomic::Ordering::Release);
60
61 let modules = get_sorted_modules();
62 for module in &modules {
63 ffi::lua_settop(state.0, 1); (module.open)(state);
65 #[cfg(debug_assertions)]
66 println!(
67 "[gmodx] Loaded OpenClose '{}' (priority: {})",
68 module.id, module.priority
69 );
70 }
71}
72
73#[allow(unused)]
74pub fn unload_all(state: &lua::State) {
75 GMOD_CLOSED.store(true, std::sync::atomic::Ordering::Release);
76
77 let modules = get_sorted_modules();
78 for module in modules.iter().rev() {
80 ffi::lua_settop(state.0, 0); (module.close)(state);
82 #[cfg(debug_assertions)]
83 println!(
84 "[gmodx] Unloaded OpenClose '{}' (priority: {})",
85 module.id, module.priority
86 );
87 }
88}