Pumpkin/pumpkin/src/block/mod.rs
Alexander Medvedev 2edb986f61 port to rand 9
again
2025-06-12 20:53:44 +02:00

252 lines
8.1 KiB
Rust

use blocks::bamboo::BambooBlock;
use blocks::barrel::BarrelBlock;
use blocks::bed::BedBlock;
use blocks::cactus::CactusBlock;
use blocks::command::CommandBlock;
use blocks::dirt_path::DirtPathBlock;
use blocks::doors::DoorBlock;
use blocks::end_portal::EndPortalBlock;
use blocks::end_portal_frame::EndPortalFrameBlock;
use blocks::farmland::FarmLandBlock;
use blocks::fence_gates::FenceGateBlock;
use blocks::fences::FenceBlock;
use blocks::fire::fire::FireBlock;
use blocks::fire::soul_fire::SoulFireBlock;
use blocks::glass_panes::GlassPaneBlock;
use blocks::iron_bars::IronBarsBlock;
use blocks::logs::LogBlock;
use blocks::nether_portal::NetherPortalBlock;
use blocks::note::NoteBlock;
use blocks::piston::piston::PistonBlock;
use blocks::piston::piston_extension::PistonExtensionBlock;
use blocks::piston::piston_head::PistonHeadBlock;
use blocks::plant::bush::BushBlock;
use blocks::plant::dry_vegetation::DryVegetationBlock;
use blocks::plant::flower::FlowerBlock;
use blocks::plant::flowerbed::FlowerbedBlock;
use blocks::plant::leaf_litter::LeafLitterBlock;
use blocks::plant::lily_pad::LilyPadBlock;
use blocks::plant::mushroom_plant::MushroomPlantBlock;
use blocks::plant::sapling::SaplingBlock;
use blocks::plant::short_plant::ShortPlantBlock;
use blocks::plant::tall_plant::TallPlantBlock;
use blocks::pumpkin::PumpkinBlock;
use blocks::redstone::buttons::ButtonBlock;
use blocks::redstone::observer::ObserverBlock;
use blocks::redstone::pressure_plate::plate::PressurePlateBlock;
use blocks::redstone::pressure_plate::weighted::WeightedPressurePlateBlock;
use blocks::redstone::rails::activator_rail::ActivatorRailBlock;
use blocks::redstone::rails::detector_rail::DetectorRailBlock;
use blocks::redstone::rails::powered_rail::PoweredRailBlock;
use blocks::redstone::rails::rail::RailBlock;
use blocks::redstone::redstone_block::RedstoneBlock;
use blocks::redstone::redstone_lamp::RedstoneLamp;
use blocks::redstone::redstone_torch::RedstoneTorchBlock;
use blocks::redstone::redstone_wire::RedstoneWireBlock;
use blocks::redstone::repeater::RepeaterBlock;
use blocks::redstone::target_block::TargetBlock;
use blocks::signs::SignBlock;
use blocks::slabs::SlabBlock;
use blocks::stairs::StairBlock;
use blocks::sugar_cane::SugarCaneBlock;
use blocks::torches::TorchBlock;
use blocks::trapdoor::TrapDoorBlock;
use blocks::vine::VineBlock;
use blocks::walls::WallBlock;
use blocks::{
chest::ChestBlock, furnace::FurnaceBlock, redstone::lever::LeverBlock, tnt::TNTBlock,
};
use fluid::lava::FlowingLava;
use fluid::water::FlowingWater;
use loot::LootTableExt;
use pumpkin_data::block_properties::Integer0To15;
use pumpkin_data::entity::EntityType;
use pumpkin_data::{Block, BlockState};
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::random::{RandomGenerator, get_seed, xoroshiro128::Xoroshiro};
use pumpkin_world::BlockStateId;
use pumpkin_world::item::ItemStack;
use rand::Rng;
use crate::block::registry::BlockRegistry;
use crate::entity::item::ItemEntity;
use crate::world::World;
use crate::{block::blocks::crafting_table::CraftingTableBlock, entity::player::Player};
use crate::{block::blocks::jukebox::JukeboxBlock, entity::experience_orb::ExperienceOrbEntity};
use std::sync::Arc;
pub mod blocks;
mod fluid;
mod loot;
pub mod pumpkin_block;
pub mod pumpkin_fluid;
pub mod registry;
#[must_use]
pub fn default_registry() -> Arc<BlockRegistry> {
let mut manager = BlockRegistry::default();
// Blocks
manager.register(BedBlock);
manager.register(SaplingBlock);
manager.register(CactusBlock);
manager.register(ChestBlock);
manager.register(CraftingTableBlock);
manager.register(DirtPathBlock);
manager.register(DoorBlock);
manager.register(FarmLandBlock);
manager.register(FenceGateBlock);
manager.register(FenceBlock);
manager.register(FurnaceBlock);
manager.register(GlassPaneBlock);
manager.register(IronBarsBlock);
manager.register(JukeboxBlock);
manager.register(LogBlock);
manager.register(BambooBlock);
manager.register(SignBlock);
manager.register(SlabBlock);
manager.register(StairBlock);
manager.register(ShortPlantBlock);
manager.register(DryVegetationBlock);
manager.register(LilyPadBlock);
manager.register(SugarCaneBlock);
manager.register(VineBlock);
manager.register(TNTBlock);
manager.register(BushBlock);
manager.register(FlowerBlock);
manager.register(TorchBlock);
manager.register(TrapDoorBlock);
manager.register(MushroomPlantBlock);
manager.register(FlowerbedBlock);
manager.register(LeafLitterBlock);
manager.register(WallBlock);
manager.register(NetherPortalBlock);
manager.register(TallPlantBlock);
manager.register(NoteBlock);
manager.register(PumpkinBlock);
manager.register(CommandBlock);
manager.register(PressurePlateBlock);
manager.register(WeightedPressurePlateBlock);
manager.register(EndPortalBlock);
manager.register(EndPortalFrameBlock);
// Fire
manager.register(SoulFireBlock);
manager.register(FireBlock);
// Redstone
manager.register(ButtonBlock);
manager.register(LeverBlock);
manager.register(ObserverBlock);
// Piston
manager.register(PistonBlock);
manager.register(PistonExtensionBlock);
manager.register(PistonHeadBlock);
manager.register(RedstoneBlock);
manager.register(RedstoneLamp);
manager.register(RedstoneTorchBlock);
manager.register(RedstoneWireBlock);
manager.register(RepeaterBlock);
manager.register(TargetBlock);
manager.register(BarrelBlock);
// Rails
manager.register(RailBlock);
manager.register(ActivatorRailBlock);
manager.register(DetectorRailBlock);
manager.register(PoweredRailBlock);
// Fluids
manager.register_fluid(FlowingWater);
manager.register_fluid(FlowingLava);
Arc::new(manager)
}
#[derive(Clone)]
pub struct BlockEvent {
pub pos: BlockPos,
pub r#type: u8,
pub data: u8,
}
pub async fn drop_loot(
world: &Arc<World>,
block: &Block,
pos: &BlockPos,
experience: bool,
state_id: BlockStateId,
) {
if let Some(loot_table) = &block.loot_table {
let props =
Block::properties(block, state_id).map_or_else(Vec::new, |props| props.to_props());
for stack in loot_table.get_loot(&props) {
drop_stack(world, pos, stack).await;
}
}
if experience {
if let Some(experience) = &block.experience {
let mut random = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(get_seed()));
let amount = experience.experience.get(&mut random);
// TODO: Silk touch gives no exp
if amount > 0 {
ExperienceOrbEntity::spawn(world, pos.to_f64(), amount as u32).await;
}
}
}
}
async fn drop_stack(world: &Arc<World>, pos: &BlockPos, stack: ItemStack) {
let height = EntityType::ITEM.dimension[1] / 2.0;
let pos = Vector3::new(
f64::from(pos.0.x) + 0.5 + rand::rng().random_range(-0.25..0.25),
f64::from(pos.0.y) + 0.5 + rand::rng().random_range(-0.25..0.25) - f64::from(height),
f64::from(pos.0.z) + 0.5 + rand::rng().random_range(-0.25..0.25),
);
let entity = world.create_entity(pos, EntityType::ITEM);
let item_entity = Arc::new(ItemEntity::new(entity, stack).await);
world.spawn_entity(item_entity).await;
}
pub async fn calc_block_breaking(player: &Player, state: &BlockState, block_name: &str) -> f32 {
let hardness = state.hardness;
#[expect(clippy::float_cmp)]
if hardness == -1.0 {
// unbreakable
return 0.0;
}
let i = if player.can_harvest(state, block_name).await {
30
} else {
100
};
player.get_mining_speed(block_name).await / hardness / i as f32
}
#[derive(PartialEq)]
pub enum BlockIsReplacing {
Itself(BlockStateId),
Water(Integer0To15),
Other,
None,
}
impl BlockIsReplacing {
#[must_use]
/// Returns true if the block was a water source block.
pub fn water_source(&self) -> bool {
match self {
// Level 0 means the water is a source block
Self::Water(level) => *level == Integer0To15::L0,
_ => false,
}
}
}