yog_api/mods/storage/
kept.rs1mod owned;
5pub(super) mod synced;
6
7use yog_core::BlockPos;
8use yog_data::Schema;
9use yog_sync::Mutex;
10
11pub use owned::{BlockData, EntityData, PlayerData, WorldData};
12
13trait Kept: Sync {
15 fn keep(&self);
17 fn forget(&self);
19 fn gone(&self, _owner: &Gone<'_>) {}
21 fn sync(&self, _every: bool, _out: &mut dyn FnMut(synced::Outgoing)) {}
24 fn take(&self, _key: &str, _owner: &str, _bytes: &[u8]) -> bool {
26 false
27 }
28}
29
30pub(super) enum Gone<'a> {
32 Entity(&'a str),
34 Block(&'a str, BlockPos),
36}
37
38static KEPT: Mutex<Vec<&'static dyn Kept>> = Mutex::new(Vec::new());
40
41fn register(kept: &'static dyn Kept) {
42 let mut all = KEPT.lock();
43 if !all.iter().any(|k| std::ptr::addr_eq(*k, kept)) {
44 all.push(kept);
45 }
46}
47
48pub(super) fn keep_all() {
49 for kept in KEPT.lock().iter() {
50 kept.keep();
51 }
52}
53
54pub(super) fn gone(owner: &Gone<'_>) {
55 for kept in KEPT.lock().iter() {
56 kept.gone(owner);
57 }
58}
59
60pub(super) fn sync(every: bool, out: &mut dyn FnMut(synced::Outgoing)) {
61 for kept in KEPT.lock().iter() {
62 kept.sync(every, out);
63 }
64}
65
66pub(super) fn take(key: &str, owner: &str, bytes: &[u8]) -> bool {
67 KEPT.lock().iter().any(|kept| kept.take(key, owner, bytes))
68}
69
70pub(super) fn forget_world() {
71 for kept in KEPT.lock().iter() {
72 kept.forget();
73 }
74}
75
76pub struct GameData<T> {
79 key: &'static str,
80 slot: Mutex<Option<T>>,
81}
82
83impl<T: Schema + Default + Send + 'static> GameData<T> {
84 pub const fn new(key: &'static str) -> Self {
85 GameData {
86 key,
87 slot: Mutex::new(None),
88 }
89 }
90
91 pub fn with<R>(&'static self, read: impl FnOnce(&T) -> R) -> R {
93 let mut slot = self.slot.lock();
94 read(slot.get_or_insert_with(|| super::game().get_or_default(self.key)))
95 }
96
97 pub fn with_mut<R>(&'static self, change: impl FnOnce(&mut T) -> R) -> R {
99 let mut slot = self.slot.lock();
100 let value = slot.get_or_insert_with(|| super::game().get_or_default(self.key));
101 let out = change(value);
102 let store = super::game();
103 store.set(self.key, value);
104 if let Err(e) = store.flush() {
105 crate::error!("[{}] couldn't save its data: {e}", crate::mod_id());
106 }
107 out
108 }
109}