Pumpkin/pumpkin/src/block/blocks/tnt.rs
Alexander Medvedev 1edbfa7289 Implement Piston 1/2
Not fully done
2025-05-12 19:42:55 +02:00

110 lines
3.1 KiB
Rust

use std::sync::Arc;
use crate::block::pumpkin_block::PumpkinBlock;
use crate::block::registry::BlockActionResult;
use crate::entity::player::Player;
use crate::entity::tnt::TNTEntity;
use crate::server::Server;
use crate::world::World;
use async_trait::async_trait;
use pumpkin_data::Block;
use pumpkin_data::entity::EntityType;
use pumpkin_data::item::Item;
use pumpkin_data::sound::SoundCategory;
use pumpkin_macros::pumpkin_block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::BlockStateId;
use pumpkin_world::world::BlockFlags;
use rand::Rng;
use super::redstone::block_receives_redstone_power;
#[pumpkin_block("minecraft:tnt")]
pub struct TNTBlock;
impl TNTBlock {
pub async fn prime(world: &Arc<World>, location: &BlockPos) {
let entity = world.create_entity(location.to_f64(), EntityType::TNT);
let pos = entity.pos.load();
let tnt = Arc::new(TNTEntity::new(entity, DEFAULT_POWER, DEFAULT_FUSE));
world.spawn_entity(tnt).await;
world
.play_sound(
pumpkin_data::sound::Sound::EntityTntPrimed,
SoundCategory::Blocks,
&pos,
)
.await;
world
.set_block_state(location, 0, BlockFlags::NOTIFY_ALL)
.await;
}
}
const DEFAULT_FUSE: u32 = 80;
const DEFAULT_POWER: f32 = 4.0;
#[async_trait]
impl PumpkinBlock for TNTBlock {
async fn use_with_item(
&self,
_block: &Block,
player: &Player,
location: BlockPos,
item: &Item,
_server: &Server,
_world: &Arc<World>,
) -> BlockActionResult {
if *item != Item::FLINT_AND_STEEL || *item == Item::FIRE_CHARGE {
return BlockActionResult::Continue;
}
let world = player.world().await;
Self::prime(&world, &location).await;
BlockActionResult::Consume
}
async fn placed(
&self,
world: &Arc<World>,
_block: &Block,
_state_id: BlockStateId,
pos: &BlockPos,
_old_state_id: BlockStateId,
_notify: bool,
) {
if block_receives_redstone_power(world, pos).await {
Self::prime(world, pos).await;
}
}
async fn on_neighbor_update(
&self,
world: &Arc<World>,
_block: &Block,
pos: &BlockPos,
_source_block: &Block,
_notify: bool,
) {
if block_receives_redstone_power(world, pos).await {
Self::prime(world, pos).await;
}
}
async fn explode(&self, _block: &Block, world: &Arc<World>, location: BlockPos) {
let entity = world.create_entity(location.to_f64(), EntityType::TNT);
let angle = rand::random::<f64>() * std::f64::consts::TAU;
entity
.set_velocity(Vector3::new(-angle.sin() * 0.02, 0.2, -angle.cos() * 0.02))
.await;
let fuse = rand::thread_rng().gen_range(0..DEFAULT_FUSE / 4) + DEFAULT_FUSE / 8;
let tnt = Arc::new(TNTEntity::new(entity, DEFAULT_POWER, fuse));
world.spawn_entity(tnt).await;
}
fn should_drop_items_on_explosion(&self) -> bool {
false
}
}