From 8be5ed1e58567b3fb443894c4e587393adce4550 Mon Sep 17 00:00:00 2001 From: Oswald <136677276+oswaldsch@users.noreply.github.com> Date: Mon, 24 Aug 2026 07:56:10 +0200 Subject: [PATCH] fix: match vanillas generation for huge mushrooms (#2430) --- .../feature/features/huge_brown_mushroom.rs | 68 +++++++++++++++---- .../feature/features/huge_red_mushroom.rs | 61 +++++++++++++---- 2 files changed, 101 insertions(+), 28 deletions(-) diff --git a/crates/pumpkin-world/src/generation/feature/features/huge_brown_mushroom.rs b/crates/pumpkin-world/src/generation/feature/features/huge_brown_mushroom.rs index 4e9b0e850..cc5d806b7 100644 --- a/crates/pumpkin-world/src/generation/feature/features/huge_brown_mushroom.rs +++ b/crates/pumpkin-world/src/generation/feature/features/huge_brown_mushroom.rs @@ -1,11 +1,27 @@ -use pumpkin_data::Block; -use pumpkin_util::{math::position::BlockPos, random::RandomGenerator, random::RandomImpl}; +use pumpkin_data::{ + Block, BlockState, + block_properties::{BlockProperties, BrownMushroomBlockLikeProperties}, +}; +use pumpkin_util::{ + math::position::BlockPos, + random::{RandomGenerator, RandomImpl}, +}; use crate::generation::proto_chunk::GenerationCache; +pub fn mushroom_tree_height(random: &mut RandomGenerator) -> i32 { + let mut height = random.next_bounded_i32(3) + 4; + if random.next_bounded_i32(12) == 0 { + height *= 2; + } + height +} + pub struct HugeBrownMushroomFeature; impl HugeBrownMushroomFeature { + const FOLIAGE_RADIUS: i32 = 3; + #[allow(clippy::unused_self)] pub fn generate( &self, @@ -16,23 +32,47 @@ impl HugeBrownMushroomFeature { random: &mut RandomGenerator, pos: BlockPos, ) -> bool { - let height = random.next_bounded_i32(3) + 4; + let tree_height = mushroom_tree_height(random); - for i in 0..height { - let stem_pos = BlockPos::new(pos.0.x, pos.0.y + i, pos.0.z); - chunk.set_block_state(&stem_pos.0, Block::MUSHROOM_STEM.default_state); - } + let radius = Self::FOLIAGE_RADIUS; + let cap_y = pos.0.y + tree_height; + for j in -radius..=radius { + for k in -radius..=radius { + let on_x_edge = j == -radius || j == radius; + let on_z_edge = k == -radius || k == radius; - let cap_y = pos.0.y + height; - for dx in -2i32..=2 { - for dz in -2i32..=2 { - let is_corner = dx.abs() == 2 && dz.abs() == 2; - if !is_corner { - let cap_pos = BlockPos::new(pos.0.x + dx, cap_y, pos.0.z + dz); - chunk.set_block_state(&cap_pos.0, Block::BROWN_MUSHROOM_BLOCK.default_state); + if on_x_edge && on_z_edge { + continue; } + + let props = BrownMushroomBlockLikeProperties { + up: true, + down: false, + west: j == -radius || (on_z_edge && j == 1 - radius), + east: j == radius || (on_z_edge && j == radius - 1), + north: k == -radius || (on_x_edge && k == 1 - radius), + south: k == radius || (on_x_edge && k == radius - 1), + }; + let state_id = props.to_state_id(&Block::BROWN_MUSHROOM_BLOCK); + let cap_pos = BlockPos::new(pos.0.x + j, cap_y, pos.0.z + k); + chunk.set_block_state(&cap_pos.0, BlockState::from_id(state_id)); } } + + let stem_props = BrownMushroomBlockLikeProperties { + up: false, + down: false, + north: true, + east: true, + south: true, + west: true, + }; + let stem_state = BlockState::from_id(stem_props.to_state_id(&Block::MUSHROOM_STEM)); + for i in 0..tree_height { + let stem_pos = BlockPos::new(pos.0.x, pos.0.y + i, pos.0.z); + chunk.set_block_state(&stem_pos.0, stem_state); + } + true } } diff --git a/crates/pumpkin-world/src/generation/feature/features/huge_red_mushroom.rs b/crates/pumpkin-world/src/generation/feature/features/huge_red_mushroom.rs index b6a56f68a..dd4dff4e2 100644 --- a/crates/pumpkin-world/src/generation/feature/features/huge_red_mushroom.rs +++ b/crates/pumpkin-world/src/generation/feature/features/huge_red_mushroom.rs @@ -1,11 +1,16 @@ -use pumpkin_data::Block; -use pumpkin_util::{math::position::BlockPos, random::RandomGenerator, random::RandomImpl}; +use pumpkin_data::{ + Block, BlockState, + block_properties::{BlockProperties, BrownMushroomBlockLikeProperties}, +}; +use pumpkin_util::{math::position::BlockPos, random::RandomGenerator}; use crate::generation::proto_chunk::GenerationCache; pub struct HugeRedMushroomFeature; impl HugeRedMushroomFeature { + const FOLIAGE_RADIUS: i32 = 2; + #[allow(clippy::unused_self)] pub fn generate( &self, @@ -16,23 +21,51 @@ impl HugeRedMushroomFeature { random: &mut RandomGenerator, pos: BlockPos, ) -> bool { - let height = random.next_bounded_i32(3) + 5; + let tree_height = super::huge_brown_mushroom::mushroom_tree_height(random); - for i in 0..height { - let stem_pos = BlockPos::new(pos.0.x, pos.0.y + i, pos.0.z); - chunk.set_block_state(&stem_pos.0, Block::MUSHROOM_STEM.default_state); - } + let radius = Self::FOLIAGE_RADIUS; + for i in (tree_height - 3)..=tree_height { + let j = if i < tree_height { radius } else { radius - 1 }; + let k = radius - 2; - let cap_y = pos.0.y + height; - for dy in 0..=2 { - let radius = if dy == 0 { 2 } else { 1 }; - for dx in -radius..=radius { - for dz in -radius..=radius { - let cap_pos = BlockPos::new(pos.0.x + dx, cap_y + dy, pos.0.z + dz); - chunk.set_block_state(&cap_pos.0, Block::RED_MUSHROOM_BLOCK.default_state); + for l in -j..=j { + for m in -j..=j { + let on_x_edge = l == -j || l == j; + let on_z_edge = m == -j || m == j; + + if i < tree_height && on_x_edge == on_z_edge { + continue; + } + + let props = BrownMushroomBlockLikeProperties { + up: i >= tree_height - 1, + down: false, + west: l < -k, + east: l > k, + north: m < -k, + south: m > k, + }; + let state_id = props.to_state_id(&Block::RED_MUSHROOM_BLOCK); + let cap_pos = BlockPos::new(pos.0.x + l, pos.0.y + i, pos.0.z + m); + chunk.set_block_state(&cap_pos.0, BlockState::from_id(state_id)); } } } + + let stem_props = BrownMushroomBlockLikeProperties { + up: false, + down: false, + north: true, + east: true, + south: true, + west: true, + }; + let stem_state = BlockState::from_id(stem_props.to_state_id(&Block::MUSHROOM_STEM)); + for i in 0..tree_height { + let stem_pos = BlockPos::new(pos.0.x, pos.0.y + i, pos.0.z); + chunk.set_block_state(&stem_pos.0, stem_state); + } + true } }