feat(block): implement cartography table block

This commit is contained in:
Alexander Medvedev 2026-08-12 21:03:58 +02:00
parent 5f74b162cd
commit 1be04b9441
4 changed files with 173 additions and 0 deletions

View File

@ -0,0 +1,113 @@
use std::any::Any;
use std::sync::Arc;
use crate::player::player_inventory::PlayerInventory;
use crate::screen_handler::{
InventoryPlayer, ScreenHandler, ScreenHandlerBehaviour, ScreenHandlerFuture,
};
use crate::slot::NormalSlot;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::screen::WindowType;
use pumpkin_protocol::java::server::play::SlotActionType;
use pumpkin_world::inventory::Inventory;
use pumpkin_world::inventory::SimpleInventory;
pub struct CartographyTableScreenHandler {
behaviour: ScreenHandlerBehaviour,
pub input_inventory: Arc<SimpleInventory>,
pub output_inventory: Arc<SimpleInventory>,
}
impl CartographyTableScreenHandler {
pub fn new(sync_id: u8, player_inventory: &Arc<PlayerInventory>) -> Self {
let behaviour = ScreenHandlerBehaviour::new(sync_id, Some(WindowType::CartographyTable));
let input_inventory = Arc::new(SimpleInventory::new(2));
let output_inventory = Arc::new(SimpleInventory::new(1));
let mut handler = Self {
behaviour,
input_inventory: input_inventory.clone(),
output_inventory: output_inventory.clone(),
};
for i in 0..2 {
handler.add_slot(Arc::new(NormalSlot::new(
input_inventory.clone() as Arc<dyn Inventory>,
i,
)));
}
handler.add_slot(Arc::new(NormalSlot::new(
output_inventory as Arc<dyn Inventory>,
0,
)));
let player_inventory: Arc<dyn Inventory> = player_inventory.clone();
handler.add_player_slots(&player_inventory);
handler
}
}
impl ScreenHandler for CartographyTableScreenHandler {
fn get_behaviour(&self) -> &ScreenHandlerBehaviour {
&self.behaviour
}
fn get_behaviour_mut(&mut self) -> &mut ScreenHandlerBehaviour {
&mut self.behaviour
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn on_slot_click<'a>(
&'a mut self,
slot_index: i32,
button: i32,
action_type: SlotActionType,
player: &'a dyn InventoryPlayer,
) -> ScreenHandlerFuture<'a, ()> {
Box::pin(async move {
self.internal_on_slot_click(slot_index, button, action_type, player)
.await;
})
}
fn quick_move<'a>(
&'a mut self,
_player: &'a dyn InventoryPlayer,
slot_index: i32,
) -> ScreenHandlerFuture<'a, ItemStack> {
Box::pin(async move {
let mut stack = ItemStack::EMPTY.clone();
let slot = self.get_behaviour().slots.get(slot_index as usize).cloned();
if let Some(slot) = slot {
let mut slot_stack = slot.get_cloned_stack().await;
if !slot_stack.is_empty() {
stack = slot_stack.clone();
if slot_index < 3 {
if !self.insert_item(&mut slot_stack, 3, 39, true).await {
return ItemStack::EMPTY.clone();
}
} else if !self.insert_item(&mut slot_stack, 0, 2, false).await {
return ItemStack::EMPTY.clone();
}
if slot_stack.is_empty() {
slot.set_stack(ItemStack::EMPTY.clone()).await;
} else {
slot.set_stack(slot_stack).await;
}
}
}
stack
})
}
}

View File

@ -0,0 +1,57 @@
use crate::block::registry::BlockActionResult;
use crate::block::{BlockBehaviour, BlockFuture, NormalUseArgs};
use pumpkin_data::translation;
use pumpkin_inventory::cartography_table_screen_handler::CartographyTableScreenHandler;
use pumpkin_inventory::player::player_inventory::PlayerInventory;
use pumpkin_inventory::screen_handler::{
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
};
use pumpkin_macros::pumpkin_block;
use pumpkin_util::text::TextComponent;
use std::sync::Arc;
use tokio::sync::Mutex;
#[pumpkin_block("minecraft:cartography_table")]
pub struct CartographyTableBlock;
impl BlockBehaviour for CartographyTableBlock {
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
Box::pin(async move {
args.player
.increment_stat(
pumpkin_data::statistic::StatisticCategory::Custom,
pumpkin_data::statistic::CustomStatistic::InteractWithCartographyTable as i32,
1,
)
.await;
args.player
.open_handled_screen(&CartographyTableScreenFactory, Some(*args.position))
.await;
BlockActionResult::Success
})
}
}
struct CartographyTableScreenFactory;
impl ScreenHandlerFactory for CartographyTableScreenFactory {
fn create_screen_handler<'a>(
&'a self,
sync_id: u8,
player_inventory: &'a Arc<PlayerInventory>,
_player: &'a dyn InventoryPlayer,
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
Box::pin(async move {
let handler: SharedScreenHandler = Arc::new(Mutex::new(
CartographyTableScreenHandler::new(sync_id, player_inventory),
));
Some(handler)
})
}
fn get_display_name(&self) -> TextComponent {
TextComponent::translate(translation::java::CONTAINER_CARTOGRAPHY_TABLE, [])
}
}

View File

@ -111,6 +111,7 @@ pub mod abstract_wall_mounting;
pub mod beacon; pub mod beacon;
pub mod brushable_block; pub mod brushable_block;
pub mod cartography_table;
pub mod creaking_heart; pub mod creaking_heart;
pub mod decorated_pot; pub mod decorated_pot;
pub mod loom; pub mod loom;

View File

@ -14,6 +14,7 @@ use crate::block::blocks::campfire::CampfireBlock;
use crate::block::blocks::candle_cakes::CandleCakeBlock; use crate::block::blocks::candle_cakes::CandleCakeBlock;
use crate::block::blocks::candles::CandleBlock; use crate::block::blocks::candles::CandleBlock;
use crate::block::blocks::carpet::{CarpetBlock, MossCarpetBlock, PaleMossCarpetBlock}; use crate::block::blocks::carpet::{CarpetBlock, MossCarpetBlock, PaleMossCarpetBlock};
use crate::block::blocks::cartography_table::CartographyTableBlock;
use crate::block::blocks::carved_pumpkin::CarvedPumpkinBlock; use crate::block::blocks::carved_pumpkin::CarvedPumpkinBlock;
use crate::block::blocks::cauldron::CauldronBlock; use crate::block::blocks::cauldron::CauldronBlock;
use crate::block::blocks::chests::{ChestBlock, CopperChestBlock, TrappedChestBlock}; use crate::block::blocks::chests::{ChestBlock, CopperChestBlock, TrappedChestBlock};
@ -251,6 +252,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
manager.register(StairBlock); manager.register(StairBlock);
manager.register(StonecutterBlock); manager.register(StonecutterBlock);
manager.register(LoomBlock); manager.register(LoomBlock);
manager.register(CartographyTableBlock);
manager.register(ShortPlantBlock); manager.register(ShortPlantBlock);
manager.register(DryVegetationBlock); manager.register(DryVegetationBlock);
manager.register(LilyPadBlock); manager.register(LilyPadBlock);