Pumpkin/crates/pumpkin/src/block/blocks/redstone/lightning_rod.rs
2026-09-02 15:16:42 +02:00

84 lines
3.1 KiB
Rust

use std::sync::Arc;
use crate::block::{
BlockBehaviour, EmitsRedstonePowerArgs, GetRedstonePowerArgs, OnPlaceArgs, OnScheduledTickArgs,
PathComputationType,
};
use crate::world::World;
use pumpkin_data::block_properties::LightningRodLikeProperties;
use pumpkin_data::{BlockState, BlockStateId, FacingExt};
use pumpkin_macros::pumpkin_block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::tick::TickPriority;
use pumpkin_world::world::BlockFlags;
#[pumpkin_block("minecraft:lightning_rod")]
pub struct LightningRodBlock;
impl LightningRodBlock {
pub fn trigger(world: &Arc<World>, pos: &BlockPos) {
let (block, state_id) = world.get_block_and_state_id(pos);
let mut props = LightningRodLikeProperties::from_state_id(state_id);
if !props.powered {
props.powered = true;
world.set_block_state(pos, props.to_state_id(block), BlockFlags::NOTIFY_ALL);
Self::update_neighbors(world, pos, props);
// In vanilla, it stays powered for 8 ticks (4 redstone ticks) before scheduled tick turns it off.
world.schedule_block_tick(block, *pos, 8, TickPriority::Normal);
}
}
fn update_neighbors(world: &Arc<World>, pos: &BlockPos, props: LightningRodLikeProperties) {
world.update_neighbors(pos, None);
// The block it is attached to is in the opposite of the facing direction
let attached_pos = pos.offset(props.facing.opposite().to_block_direction().to_offset());
world.update_neighbors(&attached_pos, None);
}
}
impl BlockBehaviour for LightningRodBlock {
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
let mut props = LightningRodLikeProperties::default(args.block);
props.facing = args.direction.to_facing().opposite();
props.to_state_id(args.block)
}
fn emits_redstone_power(&self, _args: EmitsRedstonePowerArgs<'_>) -> bool {
true
}
fn get_weak_redstone_power(&self, args: GetRedstonePowerArgs<'_>) -> u8 {
let props = LightningRodLikeProperties::from_state_id(args.state.id);
if props.powered { 15 } else { 0 }
}
fn get_strong_redstone_power(&self, args: GetRedstonePowerArgs<'_>) -> u8 {
let props = LightningRodLikeProperties::from_state_id(args.state.id);
// It emits strong power only in its facing direction (the direction pointing outward)
if props.powered && props.facing.to_block_direction() == args.direction {
15
} else {
0
}
}
fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) {
let state = args.world.get_block_state(args.position);
let mut props = LightningRodLikeProperties::from_state_id(state.id);
if props.powered {
props.powered = false;
args.world.set_block_state(
args.position,
props.to_state_id(args.block),
BlockFlags::NOTIFY_ALL,
);
}
}
fn is_pathfindable(&self, _state: &BlockState, _computation_type: PathComputationType) -> bool {
false
}
}