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, PlayerData, Was, 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 Block(&'a str, BlockPos),
34}
35
36static KEPT: Mutex<Vec<&'static dyn Kept>> = Mutex::new(Vec::new());
38
39fn register(kept: &'static dyn Kept) {
40 let mut all = KEPT.lock();
41 if !all.iter().any(|k| std::ptr::addr_eq(*k, kept)) {
42 all.push(kept);
43 }
44}
45
46pub(super) fn keep_all() {
47 for kept in KEPT.lock().iter() {
48 kept.keep();
49 }
50}
51
52pub(super) fn gone(owner: &Gone<'_>) {
53 for kept in KEPT.lock().iter() {
54 kept.gone(owner);
55 }
56}
57
58pub(super) fn sync(every: bool, out: &mut dyn FnMut(synced::Outgoing)) {
59 for kept in KEPT.lock().iter() {
60 kept.sync(every, out);
61 }
62}
63
64pub(super) fn take(key: &str, owner: &str, bytes: &[u8]) -> bool {
65 KEPT.lock().iter().any(|kept| kept.take(key, owner, bytes))
66}
67
68pub(super) fn forget_world() {
69 for kept in KEPT.lock().iter() {
70 kept.forget();
71 }
72}
73
74pub struct GameData<T> {
77 key: &'static str,
78 slot: Mutex<Option<T>>,
79 was: Option<Was<T>>,
80}
81
82impl<T: Schema + Default + Send + 'static> GameData<T> {
83 pub const fn new(key: &'static str) -> Self {
84 GameData {
85 key,
86 slot: Mutex::new(None),
87 was: None,
88 }
89 }
90
91 pub const fn was(mut self, was: Was<T>) -> Self {
94 self.was = Some(was);
95 self
96 }
97
98 pub fn with<R>(&'static self, read: impl FnOnce(&T) -> R) -> R {
100 let mut slot = self.slot.lock();
101 read(slot.get_or_insert_with(|| self.first()))
102 }
103
104 fn first(&self) -> T {
107 let store = super::game();
108 if let Some(value) = store.get(self.key) {
109 return value;
110 }
111 let old = self.was.as_ref().and_then(|was| {
112 let value = was.read(&store, was.key)?;
113 store.remove(was.key);
114 store.set(self.key, &value);
115 Some(value)
116 });
117 old.unwrap_or_default()
118 }
119
120 pub fn with_mut<R>(&'static self, change: impl FnOnce(&mut T) -> R) -> R {
122 let mut slot = self.slot.lock();
123 let value = slot.get_or_insert_with(|| self.first());
124 let out = change(value);
125 let store = super::game();
126 store.set(self.key, value);
127 if let Err(e) = store.flush() {
128 crate::error!("[{}] couldn't save its data: {e}", crate::mod_id());
129 }
130 out
131 }
132}