mod kept;
use std::path::PathBuf;
use yog_sync::Mutex;
use yog_sync::atomic::{AtomicBool, Ordering};
pub use kept::{GameData, PlayerData, WorldData};
pub use yog_storage::{Scope, Store, close_under, flush_all};
use crate::Registry;
use crate::event::server::life::{Saving, Started, Stopping};
static WORLD: Mutex<Option<PathBuf>> = Mutex::new(None);
static CLOSING: AtomicBool = AtomicBool::new(false);
pub fn session() -> Store {
Store::session(crate::mod_id())
}
pub fn game() -> Store {
Store::open(&game_dir(), crate::mod_id(), Scope::Game)
}
pub fn world() -> Option<Store> {
in_world(Scope::World)
}
pub fn dimension(dim: &str) -> Option<Store> {
in_world(Scope::Dimension(dim))
}
pub fn player(uuid: &str) -> Option<Store> {
in_world(Scope::Player(uuid))
}
pub fn entity(uuid: &str) -> Option<Store> {
in_world(Scope::Entity(uuid))
}
pub fn chunk(dim: &str, cx: i32, cz: i32) -> Option<Store> {
in_world(Scope::Chunk(dim, cx, cz))
}
fn in_world(scope: Scope<'_>) -> Option<Store> {
let root = WORLD.lock().clone()?;
Some(Store::open(&root, crate::mod_id(), scope))
}
fn game_dir() -> PathBuf {
crate::game::dir().map(PathBuf::from).unwrap_or_default()
}
#[doc(hidden)]
pub fn __know_world(registry: &mut Registry) {
registry.on::<Started, _>(|e, _| {
*WORLD.lock() = Some(PathBuf::from(&e.world_dir));
});
}
#[doc(hidden)]
pub fn __save_with_world(registry: &mut Registry) {
registry.on::<Stopping, _>(|_, _| CLOSING.store(true, Ordering::Release));
registry.on::<Saving, _>(|_, _| saving());
}
fn saving() {
kept::keep_all();
if let Err(e) = flush_all() {
crate::error!("[{}] couldn't save its data: {e}", crate::mod_id());
}
if !CLOSING.swap(false, Ordering::AcqRel) {
return;
}
kept::forget_world();
if let Some(root) = WORLD.lock().take()
&& let Err(e) = close_under(&root)
{
crate::error!("[{}] couldn't save its data: {e}", crate::mod_id());
}
}
#[cfg(test)]
mod tests;