use crate::entity_data;
use crate::handlers::handlers;
use crate::jni_util::guard;
use yog_abi::YogStr;
pub(super) fn grant_tag(id: &str) -> String {
format!("yog.grant.{id}")
}
pub(crate) fn queue_startup_grants(player: &str, uuid: &str) {
let h = handlers();
if !h.startup_grants.is_empty() {
h.pending_grants
.lock()
.push((player.to_owned(), uuid.to_owned(), 0));
}
}
pub(crate) fn after_tick() {
guard("startup_grants", process_pending_grants);
guard("entity data", entity_data::flush);
}
pub(super) fn process_pending_grants() {
let h = handlers();
let Some(mut pending) = h.pending_grants.try_lock() else {
return;
};
if pending.is_empty() {
return;
}
const FIRST_TRY_TICK: u32 = 2;
const MAX_TICKS: u32 = 600;
let mut still_pending = Vec::new();
for (p, u, ticks) in pending.drain(..) {
if ticks < FIRST_TRY_TICK {
still_pending.push((p, u, ticks + 1));
continue;
}
let player = YogStr::from_str(&p);
let mut all_ok = true;
for sg in &h.startup_grants {
let tag = grant_tag(&sg.id);
let tag = YogStr::from_str(&tag);
if unsafe { bridge!("playerHasTag", [S(player), S(tag)]) }.unwrap_or(false) {
continue;
}
let book = sg.book.as_ref().map(|_| yog_ids::game::WRITTEN_BOOK);
let mut ok = true;
for item_id in sg.items.iter().map(String::as_str).chain(book) {
ok &= crate::bus::call(&yog_event::player::GiveItem {
player: p.clone(),
item: item_id.to_owned(),
count: 1,
})
.unwrap_or(false);
}
if ok && unsafe { bridge!("addPlayerTag", [S(player), S(tag)]) }.unwrap_or(false) {
yog_logging::info!("startup grant {} given to {}", sg.id, p);
} else {
all_ok = false;
}
}
if !all_ok && ticks < MAX_TICKS {
still_pending.push((p, u, ticks + 1));
}
}
*pending = still_pending;
}