mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
feat(block): implement loom block
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
pub mod anvil;
|
pub mod anvil;
|
||||||
pub mod beacon_screen_handler;
|
pub mod beacon_screen_handler;
|
||||||
pub mod brewing;
|
pub mod brewing;
|
||||||
|
pub mod cartography_table_screen_handler;
|
||||||
pub mod container_click;
|
pub mod container_click;
|
||||||
pub mod crafting;
|
pub mod crafting;
|
||||||
pub mod double;
|
pub mod double;
|
||||||
@@ -47,10 +48,12 @@ pub mod furnace_like;
|
|||||||
pub mod generic_container_screen_handler;
|
pub mod generic_container_screen_handler;
|
||||||
pub mod gui_builder;
|
pub mod gui_builder;
|
||||||
pub mod lectern_screen_handler;
|
pub mod lectern_screen_handler;
|
||||||
|
pub mod loom_screen_handler;
|
||||||
pub mod merchant;
|
pub mod merchant;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod screen_handler;
|
pub mod screen_handler;
|
||||||
pub mod slot;
|
pub mod slot;
|
||||||
|
pub mod smithing_table_screen_handler;
|
||||||
pub mod stonecutter_screen_handler;
|
pub mod stonecutter_screen_handler;
|
||||||
pub mod sync_handler;
|
pub mod sync_handler;
|
||||||
pub mod window_property;
|
pub mod window_property;
|
||||||
|
|||||||
113
crates/pumpkin-inventory/src/loom_screen_handler.rs
Normal file
113
crates/pumpkin-inventory/src/loom_screen_handler.rs
Normal 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 LoomScreenHandler {
|
||||||
|
behaviour: ScreenHandlerBehaviour,
|
||||||
|
pub input_inventory: Arc<SimpleInventory>,
|
||||||
|
pub output_inventory: Arc<SimpleInventory>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoomScreenHandler {
|
||||||
|
pub fn new(sync_id: u8, player_inventory: &Arc<PlayerInventory>) -> Self {
|
||||||
|
let behaviour = ScreenHandlerBehaviour::new(sync_id, Some(WindowType::Loom));
|
||||||
|
let input_inventory = Arc::new(SimpleInventory::new(3));
|
||||||
|
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..3 {
|
||||||
|
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 LoomScreenHandler {
|
||||||
|
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 < 4 {
|
||||||
|
if !self.insert_item(&mut slot_stack, 4, 40, true).await {
|
||||||
|
return ItemStack::EMPTY.clone();
|
||||||
|
}
|
||||||
|
} else if !self.insert_item(&mut slot_stack, 0, 3, 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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
80
crates/pumpkin/src/block/blocks/loom.rs
Normal file
80
crates/pumpkin/src/block/blocks/loom.rs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
use crate::block::registry::BlockActionResult;
|
||||||
|
use crate::block::{BlockBehaviour, BlockFuture, NormalUseArgs, OnPlaceArgs};
|
||||||
|
use crate::entity::EntityBase;
|
||||||
|
|
||||||
|
use pumpkin_data::FacingExt;
|
||||||
|
use pumpkin_data::block_properties::{BlockProperties, WallTorchLikeProperties};
|
||||||
|
use pumpkin_data::translation;
|
||||||
|
use pumpkin_inventory::loom_screen_handler::LoomScreenHandler;
|
||||||
|
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:loom")]
|
||||||
|
pub struct LoomBlock;
|
||||||
|
|
||||||
|
impl BlockBehaviour for LoomBlock {
|
||||||
|
fn on_place<'a>(
|
||||||
|
&'a self,
|
||||||
|
args: OnPlaceArgs<'a>,
|
||||||
|
) -> BlockFuture<'a, pumpkin_data::BlockStateId> {
|
||||||
|
Box::pin(async move {
|
||||||
|
let mut props = WallTorchLikeProperties::default(args.block);
|
||||||
|
if let Some(facing) = args
|
||||||
|
.player
|
||||||
|
.get_entity()
|
||||||
|
.get_facing()
|
||||||
|
.opposite()
|
||||||
|
.to_horizontal_facing()
|
||||||
|
{
|
||||||
|
props.facing = facing;
|
||||||
|
}
|
||||||
|
props.to_state_id(args.block)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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::InteractWithLoom as i32,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
args.player
|
||||||
|
.open_handled_screen(&LoomScreenFactory, Some(*args.position))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
BlockActionResult::Success
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoomScreenFactory;
|
||||||
|
|
||||||
|
impl ScreenHandlerFactory for LoomScreenFactory {
|
||||||
|
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(LoomScreenHandler::new(
|
||||||
|
sync_id,
|
||||||
|
player_inventory,
|
||||||
|
)));
|
||||||
|
Some(handler)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_display_name(&self) -> TextComponent {
|
||||||
|
TextComponent::translate(translation::java::CONTAINER_LOOM, [])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -113,6 +113,7 @@ pub mod beacon;
|
|||||||
pub mod brushable_block;
|
pub mod brushable_block;
|
||||||
pub mod creaking_heart;
|
pub mod creaking_heart;
|
||||||
pub mod decorated_pot;
|
pub mod decorated_pot;
|
||||||
|
pub mod loom;
|
||||||
pub mod sniffer_egg;
|
pub mod sniffer_egg;
|
||||||
pub mod trial_spawner;
|
pub mod trial_spawner;
|
||||||
pub mod turtle_egg;
|
pub mod turtle_egg;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ use crate::block::blocks::infested::InfestedBlock;
|
|||||||
use crate::block::blocks::iron_bars::IronBarsBlock;
|
use crate::block::blocks::iron_bars::IronBarsBlock;
|
||||||
use crate::block::blocks::jigsaw::JigsawBlock;
|
use crate::block::blocks::jigsaw::JigsawBlock;
|
||||||
use crate::block::blocks::logs::LogBlock;
|
use crate::block::blocks::logs::LogBlock;
|
||||||
|
use crate::block::blocks::loom::LoomBlock;
|
||||||
use crate::block::blocks::magma::MagmaBlock;
|
use crate::block::blocks::magma::MagmaBlock;
|
||||||
use crate::block::blocks::mangrove_roots::MangroveRootsBlock;
|
use crate::block::blocks::mangrove_roots::MangroveRootsBlock;
|
||||||
use crate::block::blocks::nether_portal::NetherPortalBlock;
|
use crate::block::blocks::nether_portal::NetherPortalBlock;
|
||||||
@@ -128,6 +129,7 @@ use crate::block::blocks::sculk::sculk_vein::SculkVeinBlock;
|
|||||||
use crate::block::blocks::shelf::ShelfBlock;
|
use crate::block::blocks::shelf::ShelfBlock;
|
||||||
use crate::block::blocks::signs::SignBlock;
|
use crate::block::blocks::signs::SignBlock;
|
||||||
use crate::block::blocks::slabs::SlabBlock;
|
use crate::block::blocks::slabs::SlabBlock;
|
||||||
|
use crate::block::blocks::slime::SlimeBlock;
|
||||||
use crate::block::blocks::sniffer_egg::SnifferEggBlock;
|
use crate::block::blocks::sniffer_egg::SnifferEggBlock;
|
||||||
use crate::block::blocks::snow::LayeredSnowBlock;
|
use crate::block::blocks::snow::LayeredSnowBlock;
|
||||||
use crate::block::blocks::spawner::SpawnerBlock;
|
use crate::block::blocks::spawner::SpawnerBlock;
|
||||||
@@ -248,6 +250,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
|
|||||||
manager.register(SlimeBlock);
|
manager.register(SlimeBlock);
|
||||||
manager.register(StairBlock);
|
manager.register(StairBlock);
|
||||||
manager.register(StonecutterBlock);
|
manager.register(StonecutterBlock);
|
||||||
|
manager.register(LoomBlock);
|
||||||
manager.register(ShortPlantBlock);
|
manager.register(ShortPlantBlock);
|
||||||
manager.register(DryVegetationBlock);
|
manager.register(DryVegetationBlock);
|
||||||
manager.register(LilyPadBlock);
|
manager.register(LilyPadBlock);
|
||||||
|
|||||||
Reference in New Issue
Block a user