Skip to content

Commit d8d6676

Browse files
authored
add gourds (Pumpkin-MC#1090)
* add gourds * fix * Update stem.rs
1 parent 6e7b56a commit d8d6676

6 files changed

Lines changed: 227 additions & 0 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use async_trait::async_trait;
2+
use pumpkin_data::{
3+
Block,
4+
block_properties::{
5+
BlockProperties, EnumVariants, Integer0To7, WallTorchLikeProperties, WheatLikeProperties,
6+
},
7+
};
8+
use pumpkin_util::math::position::BlockPos;
9+
use pumpkin_world::{BlockStateId, world::BlockAccessor};
10+
11+
use crate::block::{
12+
BlockBehaviour, BlockMetadata, CanPlaceAtArgs, GetStateForNeighborUpdateArgs,
13+
blocks::plant::PlantBlockBase,
14+
};
15+
16+
type AttachedStemProperties = WallTorchLikeProperties;
17+
18+
type StemProperties = WheatLikeProperties;
19+
pub struct AttachedStemBlock;
20+
21+
impl BlockMetadata for AttachedStemBlock {
22+
fn namespace(&self) -> &'static str {
23+
"minecraft"
24+
}
25+
26+
fn ids(&self) -> &'static [&'static str] {
27+
&[
28+
Block::ATTACHED_PUMPKIN_STEM.name,
29+
Block::ATTACHED_MELON_STEM.name,
30+
]
31+
}
32+
}
33+
34+
impl AttachedStemBlock {
35+
fn get_stem(block: &Block) -> &Block {
36+
match block.id {
37+
id if id == Block::ATTACHED_PUMPKIN_STEM.id => &Block::PUMPKIN_STEM,
38+
id if id == Block::ATTACHED_MELON_STEM.id => &Block::MELON_STEM,
39+
_ => &Block::MELON_STEM, // Should never happen
40+
}
41+
}
42+
43+
fn get_gourd(block: &Block) -> &Block {
44+
match block.id {
45+
id if id == Block::ATTACHED_PUMPKIN_STEM.id => &Block::PUMPKIN,
46+
id if id == Block::ATTACHED_MELON_STEM.id => &Block::MELON,
47+
_ => &Block::MELON, // Should never happen
48+
}
49+
}
50+
}
51+
52+
#[async_trait]
53+
impl BlockBehaviour for AttachedStemBlock {
54+
async fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
55+
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
56+
}
57+
58+
async fn get_state_for_neighbor_update(
59+
&self,
60+
args: GetStateForNeighborUpdateArgs<'_>,
61+
) -> BlockStateId {
62+
let props = AttachedStemProperties::from_state_id(args.state_id, args.block);
63+
if args.direction.to_horizontal_facing() == Some(props.facing)
64+
&& args.neighbor_state_id != Self::get_gourd(args.block).default_state.id
65+
{
66+
let mut props = StemProperties::default(Self::get_stem(args.block));
67+
props.age = Integer0To7::from_index(7);
68+
return props.to_state_id(Self::get_stem(args.block));
69+
}
70+
<Self as PlantBlockBase>::get_state_for_neighbor_update(
71+
self,
72+
args.world,
73+
args.position,
74+
args.state_id,
75+
)
76+
.await
77+
}
78+
}
79+
80+
impl PlantBlockBase for AttachedStemBlock {
81+
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
82+
let block = block_accessor.get_block(pos).await;
83+
block == &Block::FARMLAND
84+
}
85+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod attached_stem;
2+
pub mod stem;
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
use crate::block::{
2+
BlockBehaviour, BlockMetadata, CanPlaceAtArgs, GetStateForNeighborUpdateArgs, RandomTickArgs,
3+
blocks::plant::PlantBlockBase,
4+
};
5+
use async_trait::async_trait;
6+
use pumpkin_data::{
7+
Block, BlockDirection,
8+
block_properties::{
9+
BlockProperties, EnumVariants, Integer0To7, WallTorchLikeProperties, WheatLikeProperties,
10+
},
11+
tag,
12+
tag::Taggable,
13+
};
14+
use pumpkin_util::{
15+
math::position::BlockPos,
16+
random::{RandomGenerator, xoroshiro128::Xoroshiro},
17+
};
18+
use pumpkin_world::{
19+
BlockStateId,
20+
world::{BlockAccessor, BlockFlags},
21+
};
22+
use rand::Rng;
23+
24+
type StemProperties = WheatLikeProperties;
25+
type AttachedStemProperties = WallTorchLikeProperties;
26+
27+
pub struct StemBlock;
28+
29+
impl BlockMetadata for StemBlock {
30+
fn namespace(&self) -> &'static str {
31+
"minecraft"
32+
}
33+
34+
fn ids(&self) -> &'static [&'static str] {
35+
&[Block::PUMPKIN_STEM.name, Block::MELON_STEM.name]
36+
}
37+
}
38+
39+
impl StemBlock {
40+
fn state_with_age(block: &Block, state: u16, age: i32) -> BlockStateId {
41+
let mut props = StemProperties::from_state_id(state, block);
42+
props.age = Integer0To7::from_index(age as u16);
43+
props.to_state_id(block)
44+
}
45+
46+
fn get_attached_stem(dir: BlockDirection, block: &Block) -> BlockStateId {
47+
let attached_block = match block.id {
48+
id if id == Block::PUMPKIN_STEM.id => &Block::ATTACHED_PUMPKIN_STEM,
49+
id if id == Block::MELON_STEM.id => &Block::ATTACHED_MELON_STEM,
50+
_ => &Block::ATTACHED_MELON_STEM, // Should never happen
51+
};
52+
let mut props = AttachedStemProperties::default(attached_block);
53+
props.facing = dir.to_horizontal_facing().unwrap();
54+
props.to_state_id(attached_block)
55+
}
56+
57+
fn get_gourd(block: &Block) -> &Block {
58+
match block.id {
59+
id if id == Block::PUMPKIN_STEM.id => &Block::PUMPKIN,
60+
id if id == Block::MELON_STEM.id => &Block::MELON,
61+
_ => &Block::MELON, // Should never happen
62+
}
63+
}
64+
}
65+
66+
#[async_trait]
67+
impl BlockBehaviour for StemBlock {
68+
async fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
69+
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
70+
}
71+
72+
async fn get_state_for_neighbor_update(
73+
&self,
74+
args: GetStateForNeighborUpdateArgs<'_>,
75+
) -> BlockStateId {
76+
<Self as PlantBlockBase>::get_state_for_neighbor_update(
77+
self,
78+
args.world,
79+
args.position,
80+
args.state_id,
81+
)
82+
.await
83+
}
84+
85+
async fn random_tick(&self, args: RandomTickArgs<'_>) {
86+
// TODO add light level and moisture check
87+
let f = 5;
88+
if rand::rng().random_range(0..=(25 / f)) == 0 {
89+
let (block, state) = args.world.get_block_and_state_id(args.position).await;
90+
let props = StemProperties::from_state_id(state, block);
91+
let age = i32::from(props.age.to_index());
92+
if age < 7 {
93+
args.world
94+
.set_block_state(
95+
args.position,
96+
Self::state_with_age(block, state, age + 1),
97+
BlockFlags::NOTIFY_NEIGHBORS,
98+
)
99+
.await;
100+
} else {
101+
let dir = BlockDirection::random_horizontal(&mut RandomGenerator::Xoroshiro(
102+
Xoroshiro::from_seed(rand::rng().random()),
103+
));
104+
let plant_block_pos = args.position.offset(dir.to_offset());
105+
let plant_block_state = args.world.get_block_state(&plant_block_pos).await;
106+
let under_block: &Block = args.world.get_block(&plant_block_pos.down()).await;
107+
if plant_block_state.is_air()
108+
&& (under_block == &Block::FARMLAND
109+
|| under_block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_DIRT))
110+
{
111+
let attached_stem = Self::get_attached_stem(dir, block);
112+
let gourd = Self::get_gourd(block);
113+
args.world
114+
.set_block_state(
115+
&plant_block_pos,
116+
gourd.default_state.id,
117+
BlockFlags::NOTIFY_NEIGHBORS,
118+
)
119+
.await;
120+
args.world
121+
.set_block_state(args.position, attached_stem, BlockFlags::NOTIFY_NEIGHBORS)
122+
.await;
123+
}
124+
}
125+
}
126+
}
127+
}
128+
129+
impl PlantBlockBase for StemBlock {
130+
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
131+
let block = block_accessor.get_block(pos).await;
132+
block == &Block::FARMLAND
133+
}
134+
}

pumpkin/src/block/blocks/plant/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod crop;
77
pub mod dry_vegetation;
88
pub mod flower;
99
pub mod flowerbed;
10+
pub mod gourds;
1011
pub mod leaf_litter;
1112
pub mod lily_pad;
1213
pub mod mushroom_plant;

pumpkin/src/block/fluid/flowing.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ pub trait FlowingFluid {
267267
return true;
268268
}
269269

270+
//TODO check if source
270271
if self.is_same_fluid(fluid, state_id) {
271272
let props = FlowingFluidProperties::from_state_id(state_id, fluid);
272273
return props.level == Level::L8 && props.falling != Falling::True;

pumpkin/src/block/registry.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ use crate::block::blocks::redstone::dispenser::DispenserBlock;
107107
use crate::block::blocks::redstone::dropper::DropperBlock;
108108

109109
use super::BlockIsReplacing;
110+
use super::blocks::plant::gourds::attached_stem::AttachedStemBlock;
111+
use super::blocks::plant::gourds::stem::StemBlock;
110112
use super::fluid::FluidBehaviour;
111113
use super::{
112114
BrokenArgs, CanPlaceAtArgs, CanUpdateAtArgs, EmitsRedstonePowerArgs, ExplodeArgs,
@@ -201,6 +203,8 @@ pub fn default_registry() -> Arc<BlockRegistry> {
201203
manager.register(SkullBlock);
202204
manager.register(ChiseledBookshelfBlock);
203205
manager.register(LecternBlock);
206+
manager.register(StemBlock);
207+
manager.register(AttachedStemBlock);
204208

205209
// Fire
206210
manager.register(SoulFireBlock);

0 commit comments

Comments
 (0)