use std::collections::HashMap;
use yog_event::storage::SyncedRow;
use yog_ids::yog::SYNCED;
use yog_sync::Mutex;
use crate::Registry;
use crate::event::client::net::Packet;
use crate::event::player::session::{Join, Leave};
use crate::event::server::game::Tick;
#[derive(Clone, Copy)]
pub(in crate::mods::storage) enum Audience {
Owner,
All,
}
pub(in crate::mods::storage) struct Outgoing {
pub owner: String,
pub to: Option<String>,
pub key: &'static str,
pub bytes: Vec<u8>,
}
static NAMES: Mutex<Option<HashMap<String, String>>> = Mutex::new(None);
type Values = HashMap<(String, String), Vec<u8>>;
static PENDING: Mutex<Option<Values>> = Mutex::new(None);
pub(super) fn pending(key: &str, owner: &str) -> Option<Vec<u8>> {
PENDING
.lock()
.as_mut()?
.remove(&(key.to_owned(), owner.to_owned()))
}
pub(in crate::mods::storage) fn listen(registry: &mut Registry) {
registry.on::<Join, _>(|e, _| joined(&e.uuid, &e.player_name));
registry.on::<Leave, _>(|e, _| {
if let Some(names) = NAMES.lock().as_mut() {
names.remove(&e.uuid);
}
});
registry.on::<Tick, _>(|_, _| super::sync(false, &mut |o| send(&o)));
registry.on_client_packet(SYNCED, |p: &Packet| received(&p.payload));
}
fn joined(uuid: &str, name: &str) {
NAMES
.lock()
.get_or_insert_with(HashMap::new)
.insert(uuid.to_owned(), name.to_owned());
super::sync(true, &mut |o| {
if o.to.as_deref().is_none_or(|to| to == uuid) {
send_to(name, &o);
}
});
}
fn send(o: &Outgoing) {
match &o.to {
Some(uuid) => {
let name = NAMES.lock().as_ref().and_then(|n| n.get(uuid).cloned());
if let Some(name) = name {
send_to(&name, o);
}
}
None => {
for name in crate::event::player::online() {
send_to(&name, o);
}
}
}
}
fn send_to(name: &str, o: &Outgoing) {
let row = SyncedRow {
kind: crate::mod_id().to_owned(),
owner: o.owner.clone(),
key: o.key.to_owned(),
bytes: o.bytes.clone(),
};
crate::net::send_to_player(name, SYNCED, yog_data::to_bytes(&row));
}
fn received(payload: &[u8]) {
if super::super::world_open() {
return;
}
let Ok(row) = yog_data::read_bytes::<SyncedRow>(payload) else {
crate::error!("[{}] a synced value didn't arrive whole", crate::mod_id());
return;
};
arrived(row);
}
pub(in crate::mods::storage) fn arrived(row: SyncedRow) {
if row.kind != crate::mod_id() || super::take(&row.key, &row.owner, &row.bytes) {
return;
}
PENDING
.lock()
.get_or_insert_with(HashMap::new)
.insert((row.key, row.owner), row.bytes);
}