use crate::crafting::check_if_matches_crafting; use crate::{Container, WindowType}; use pumpkin_util::math::position::WorldPosition; use pumpkin_world::block::block_registry::Block; use pumpkin_world::item::ItemStack; use std::sync::Arc; use tokio::sync::Mutex; pub struct OpenContainer { // TODO: unique id should be here // TODO: should this be uuid? players: Vec, container: Arc>>, location: Option, block: Option, } impl OpenContainer { pub fn try_open(&self, player_id: i32) -> Option<&Arc>>> { if !self.players.contains(&player_id) { log::debug!("couldn't open container"); return None; } let container = &self.container; Some(container) } pub fn add_player(&mut self, player_id: i32) { if !self.players.contains(&player_id) { self.players.push(player_id); } } pub fn remove_player(&mut self, player_id: i32) { if let Some(index) = self.players.iter().enumerate().find_map(|(index, id)| { if *id == player_id { Some(index) } else { None } }) { self.players.remove(index); } } pub fn new_empty_container( player_id: i32, location: Option, block: Option, ) -> Self { Self { players: vec![player_id], container: Arc::new(Mutex::new(Box::new(C::default()))), location, block, } } pub fn is_location(&self, try_position: WorldPosition) -> bool { if let Some(location) = self.location { location == try_position } else { false } } pub async fn clear_all_slots(&self) { self.container.lock().await.clear_all_slots(); } pub fn clear_all_players(&mut self) { self.players = vec![]; } pub fn all_player_ids(&self) -> Vec { self.players.clone() } pub fn get_number_of_players(&self) -> usize { self.players.len() } pub fn get_location(&self) -> Option { self.location } pub async fn set_location(&mut self, location: Option) { self.location = location; } pub fn get_block(&self) -> Option { self.block.clone() } } #[derive(Default)] pub struct Chest([Option; 27]); impl Chest { pub fn new() -> Self { Self([None; 27]) } } impl Container for Chest { fn window_type(&self) -> &'static WindowType { &WindowType::Generic9x3 } fn window_name(&self) -> &'static str { "Chest" } fn all_slots(&mut self) -> Vec<&mut Option> { self.0.iter_mut().collect() } fn all_slots_ref(&self) -> Vec> { self.0.iter().map(|slot| slot.as_ref()).collect() } } #[derive(Default)] pub struct CraftingTable { input: [[Option; 3]; 3], output: Option, } impl Container for CraftingTable { fn window_type(&self) -> &'static WindowType { &WindowType::CraftingTable } fn window_name(&self) -> &'static str { "Crafting Table" } fn all_slots(&mut self) -> Vec<&mut Option> { let slots = vec![&mut self.output]; let slots = slots .into_iter() .chain(self.input.iter_mut().flatten()) .collect(); slots } fn all_slots_ref(&self) -> Vec> { let slots = vec![self.output.as_ref()]; let slots = slots .into_iter() .chain(self.input.iter().flatten().map(|i| i.as_ref())) .collect(); slots } fn all_combinable_slots(&self) -> Vec> { self.input.iter().flatten().map(|s| s.as_ref()).collect() } fn all_combinable_slots_mut(&mut self) -> Vec<&mut Option> { self.input.iter_mut().flatten().collect() } fn craft(&mut self) -> bool { let old_output = self.output; self.output = check_if_matches_crafting(self.input); old_output != self.output || self.input.iter().flatten().any(|s| s.is_some()) || self.output.is_some() } fn crafting_output_slot(&self) -> Option { Some(0) } fn slot_in_crafting_input_slots(&self, slot: &usize) -> bool { (1..10).contains(slot) } fn recipe_used(&mut self) { self.input.iter_mut().flatten().for_each(|slot| { if let Some(item) = slot { if item.item_count > 1 { item.item_count -= 1; } else { *slot = None; } } }) } } #[derive(Default)] pub struct Furnace { cook: Option, fuel: Option, output: Option, } impl Container for Furnace { fn window_type(&self) -> &'static WindowType { &WindowType::Furnace } fn window_name(&self) -> &'static str { "Furnace" } fn all_slots(&mut self) -> Vec<&mut Option> { let mut slots = vec![&mut self.cook]; slots.push(&mut self.fuel); slots.push(&mut self.output); slots } fn all_slots_ref(&self) -> Vec> { let mut slots = vec![self.cook.as_ref()]; slots.push(self.fuel.as_ref()); slots.push(self.output.as_ref()); slots } }