Less unwraps more fun

This commit is contained in:
Alexander Medvedev 2025-05-18 18:55:19 +02:00
parent d6be9823a5
commit 68c24366c3
61 changed files with 475 additions and 437 deletions

View File

@ -23,6 +23,7 @@ mod player_position;
mod player_position_rotation;
mod player_rotation;
mod player_session;
mod set_command_block;
mod set_creative_slot;
mod set_held_item;
mod swing_arm;
@ -55,6 +56,7 @@ pub use player_position::*;
pub use player_position_rotation::*;
pub use player_rotation::*;
pub use player_session::*;
pub use set_command_block::*;
pub use set_creative_slot::*;
pub use set_held_item::*;
pub use swing_arm::*;

View File

@ -0,0 +1,35 @@
use pumpkin_data::packet::serverbound::PLAY_SET_COMMAND_BLOCK;
use pumpkin_macros::packet;
use pumpkin_util::math::position::BlockPos;
use serde::Deserialize;
use crate::codec::var_int::VarInt;
#[derive(Deserialize)]
#[packet(PLAY_SET_COMMAND_BLOCK)]
pub struct SSetCommandBlock {
pub pos: BlockPos,
pub command: String,
pub mode: VarInt,
pub flags: i8,
}
pub enum CommandBlockMode {
Chain,
Repeating,
/// Redstone only
Impulse,
}
impl TryFrom<VarInt> for CommandBlockMode {
type Error = ();
fn try_from(value: VarInt) -> Result<Self, Self::Error> {
match value.0 {
0 => Ok(Self::Chain),
1 => Ok(Self::Repeating),
2 => Ok(Self::Impulse),
_ => Err(()),
}
}
}

View File

@ -70,7 +70,6 @@ impl BlockEntity for BarrelBlockEntity {
impl BarrelBlockEntity {
pub const ID: &'static str = "minecraft:barrel";
pub fn new(position: BlockPos) -> Self {
println!("Creating barrel");
Self {
position,
items: from_fn(|_| Arc::new(Mutex::new(ItemStack::EMPTY))),

View File

@ -0,0 +1,54 @@
use std::sync::atomic::AtomicBool;
use async_trait::async_trait;
use pumpkin_util::math::position::BlockPos;
use super::BlockEntity;
pub struct CommandBlockEntity {
pub position: BlockPos,
pub powered: AtomicBool,
_condition_met: AtomicBool,
_auto: AtomicBool,
pub dirty: AtomicBool,
}
impl CommandBlockEntity {
pub const ID: &'static str = "minecraft:command_block";
pub fn new(position: BlockPos) -> Self {
Self {
position,
powered: AtomicBool::new(false),
_condition_met: AtomicBool::new(false),
_auto: AtomicBool::new(false),
dirty: AtomicBool::new(false),
}
}
}
#[async_trait]
impl BlockEntity for CommandBlockEntity {
fn identifier(&self) -> &'static str {
Self::ID
}
fn get_position(&self) -> BlockPos {
self.position
}
fn from_nbt(_nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self
where
Self: Sized,
{
Self::new(position)
}
async fn write_nbt(&self, _nbt: &mut pumpkin_nbt::compound::NbtCompound) {}
fn is_dirty(&self) -> bool {
self.dirty.load(std::sync::atomic::Ordering::Relaxed)
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}

View File

@ -16,6 +16,7 @@ use crate::{inventory::Inventory, world::SimpleWorld};
pub mod barrel;
pub mod bed;
pub mod chest;
pub mod command_block;
pub mod comparator;
pub mod piston;
pub mod sign;

View File

@ -33,7 +33,7 @@ impl PistonBlockEntity {
if self.last_progress.load() < 1.0 {
let pos = self.position;
world.remove_block_entity(&pos).await;
if world.get_block(&pos).await.unwrap() == Block::MOVING_PISTON {
if world.get_block(&pos).await == Block::MOVING_PISTON {
let state = if self.source {
Block::AIR.default_state_id
} else {
@ -72,7 +72,7 @@ impl BlockEntity for PistonBlockEntity {
if current_progress >= 1.0 {
let pos = self.position;
world.remove_block_entity(&pos).await;
if world.get_block(&pos).await.unwrap() == Block::MOVING_PISTON {
if world.get_block(&pos).await == Block::MOVING_PISTON {
if self.pushed_block_state.is_air() {
world
.clone()

View File

@ -44,7 +44,7 @@ pub trait SimpleWorld: Send + Sync {
flags: BlockFlags,
) -> BlockStateId;
async fn get_block(&self, position: &BlockPos) -> Result<pumpkin_data::Block, GetBlockError>;
async fn get_block(&self, position: &BlockPos) -> pumpkin_data::Block;
async fn update_neighbor(
self: Arc<Self>,

View File

@ -47,14 +47,11 @@ impl PumpkinBlock for BedBlock {
) -> bool {
let facing = player.living_entity.entity.get_horizontal_facing();
world
.get_block_state(block_pos)
.await
.is_ok_and(|state| state.replaceable())
world.get_block_state(block_pos).await.replaceable()
&& world
.get_block_state(&block_pos.offset(facing.to_offset()))
.await
.is_ok_and(|state| state.replaceable())
.replaceable()
}
async fn on_place(

View File

@ -33,12 +33,8 @@ impl PumpkinBlock for CactusBlock {
}
async fn random_tick(&self, block: &Block, world: &Arc<World>, pos: &BlockPos) {
if world.get_block_state(&pos.up()).await.unwrap().is_air() {
let state_id = world
.get_block_state(pos)
.await
.expect("`location` should be a cactus")
.id;
if world.get_block_state(&pos.up()).await.is_air() {
let state_id = world.get_block_state(pos).await.id;
let age = CactusLikeProperties::from_state_id(state_id, block).age;
if age == Integer0To15::L15 {
world
@ -112,18 +108,13 @@ async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
for direction in BlockDirection::horizontal() {
let (block, state) = world
.get_block_and_block_state(&block_pos.offset(direction.to_offset()))
.await
.unwrap();
.await;
if state.is_solid() || block == Block::LAVA {
return false;
}
}
let block = world.get_block(&block_pos.down()).await.unwrap();
let block = world.get_block(&block_pos.down()).await;
// TODO: use tags
(block == Block::CACTUS || block.is_tagged_with("minecraft:sand").unwrap())
&& !world
.get_block_state(&block_pos.up())
.await
.unwrap()
.is_liquid()
&& !world.get_block_state(&block_pos.up()).await.is_liquid()
}

View File

@ -168,12 +168,9 @@ async fn compute_chest_props(
return (ChestType::Single, chest_facing);
};
let Ok((clicked_block, clicked_block_state)) = world
let (clicked_block, clicked_block_state) = world
.get_block_and_block_state(&block_pos.offset(face.to_offset()))
.await
else {
return (ChestType::Single, chest_facing);
};
.await;
if clicked_block == *block {
let clicked_props =
@ -230,12 +227,9 @@ async fn get_chest_properties_if_can_connect(
direction: HorizontalFacing,
wanted_type: ChestType,
) -> Option<ChestLikeProperties> {
let Ok((neighbor_block, neighbor_block_state)) = world
let (neighbor_block, neighbor_block_state) = world
.get_block_and_block_state(&block_pos.offset(direction.to_offset()))
.await
else {
return None;
};
.await;
if neighbor_block != *block {
return None;

View File

@ -0,0 +1,91 @@
use std::sync::{Arc, atomic::Ordering};
use async_trait::async_trait;
use pumpkin_data::Block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::{
block::entities::{BlockEntity, command_block::CommandBlockEntity},
chunk::TickPriority,
};
use crate::{
block::pumpkin_block::{BlockMetadata, PumpkinBlock},
world::World,
};
use super::redstone::block_receives_redstone_power;
pub struct CommandBlock;
impl CommandBlock {
pub async fn update(
world: &World,
block: &Block,
command_block: CommandBlockEntity,
pos: &BlockPos,
powered: bool,
) {
if command_block.powered.load(Ordering::Relaxed) == powered {
return;
}
command_block.powered.store(powered, Ordering::Relaxed);
if powered {
world
.schedule_block_tick(block, *pos, 1, TickPriority::Normal)
.await;
}
}
}
impl BlockMetadata for CommandBlock {
fn namespace(&self) -> &'static str {
"minecraft"
}
fn ids(&self) -> &'static [&'static str] {
&[
Block::COMMAND_BLOCK.name,
Block::CHAIN_COMMAND_BLOCK.name,
Block::REPEATING_COMMAND_BLOCK.name,
]
}
}
#[async_trait]
impl PumpkinBlock for CommandBlock {
async fn on_neighbor_update(
&self,
world: &Arc<World>,
block: &Block,
pos: &BlockPos,
_source_block: &Block,
_notify: bool,
) {
if let Some((nbt, block_entity)) = world.get_block_entity(pos).await {
let command_entity = CommandBlockEntity::from_nbt(&nbt, *pos);
if block_entity.identifier() != command_entity.identifier() {
return;
}
Self::update(
world,
block,
command_entity,
pos,
block_receives_redstone_power(world, pos).await,
)
.await;
}
}
async fn on_scheduled_tick(&self, world: &Arc<World>, _block: &Block, pos: &BlockPos) {
if let Some((nbt, block_entity)) = world.get_block_entity(pos).await {
let command_entity = CommandBlockEntity::from_nbt(&nbt, *pos);
if block_entity.identifier() != command_entity.identifier() {
return;
}
// TODO
}
}
}

View File

@ -78,6 +78,6 @@ impl PumpkinBlock for DirtPathBlock {
}
async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
let state = world.get_block_state(&block_pos.up()).await.unwrap();
let state = world.get_block_state(&block_pos.up()).await;
!state.is_solid() // TODO: add fence gate block
}

View File

@ -31,7 +31,7 @@ use crate::world::World;
type DoorProperties = pumpkin_data::block_properties::OakDoorLikeProperties;
async fn toggle_door(world: &Arc<World>, block_pos: &BlockPos) {
let (block, block_state) = world.get_block_and_block_state(block_pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(block_pos).await;
let mut door_props = DoorProperties::from_state_id(block_state.id, &block);
door_props.open = !door_props.open;
@ -41,7 +41,7 @@ async fn toggle_door(world: &Arc<World>, block_pos: &BlockPos) {
};
let other_pos = block_pos.offset(other_half.to_offset());
let (other_block, other_state_id) = world.get_block_and_block_state(&other_pos).await.unwrap();
let (other_block, other_state_id) = world.get_block_and_block_state(&other_pos).await;
let mut other_door_props = DoorProperties::from_state_id(other_state_id.id, &other_block);
other_door_props.open = door_props.open;
@ -100,19 +100,18 @@ async fn get_hinge(
let top_pos = pos.up();
let left_dir = facing.rotate_counter_clockwise();
let left_pos = pos.offset(left_dir.to_block_direction().to_offset());
let left_state = world.get_block_state(&left_pos).await.unwrap();
let left_state = world.get_block_state(&left_pos).await;
let top_facing = top_pos.offset(facing.to_block_direction().to_offset());
let top_state = world.get_block_state(&top_facing).await.unwrap();
let top_state = world.get_block_state(&top_facing).await;
let right_dir = facing.rotate_clockwise();
let right_pos = pos.offset(right_dir.to_block_direction().to_offset());
let right_state = world.get_block_state(&right_pos).await.unwrap();
let right_state = world.get_block_state(&right_pos).await;
let top_right = top_pos.offset(facing.to_block_direction().to_offset());
let top_right_state = world.get_block_state(&top_right).await.unwrap();
let top_right_state = world.get_block_state(&top_right).await;
let has_left_door = world
.get_block(&left_pos)
.await
.unwrap()
.is_tagged_with("minecraft:doors")
.unwrap()
&& DoorProperties::from_state_id(left_state.id, block).half == DoubleBlockHalf::Lower;
@ -120,7 +119,6 @@ async fn get_hinge(
let has_right_door = world
.get_block(&right_pos)
.await
.unwrap()
.is_tagged_with("minecraft:doors")
.unwrap()
&& DoorProperties::from_state_id(right_state.id, block).half == DoubleBlockHalf::Lower;
@ -263,7 +261,7 @@ impl PumpkinBlock for DoorBlock {
_source_block: &Block,
_notify: bool,
) {
let block_state = world.get_block_state(pos).await.unwrap();
let block_state = world.get_block_state(pos).await;
let mut door_props = DoorProperties::from_state_id(block_state.id, block);
let other_half = match door_props.half {
@ -271,8 +269,7 @@ impl PumpkinBlock for DoorBlock {
DoubleBlockHalf::Lower => BlockDirection::Up,
};
let other_pos = pos.offset(other_half.to_offset());
let (other_block, other_state_id) =
world.get_block_and_block_state(&other_pos).await.unwrap();
let (other_block, other_state_id) = world.get_block_and_block_state(&other_pos).await;
let powered = block_receives_redstone_power(world, pos).await
|| block_receives_redstone_power(world, &other_pos).await;
@ -343,12 +340,8 @@ impl PumpkinBlock for DoorBlock {
}
async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
world
.get_block_state(&block_pos.up())
.await
.is_ok_and(|state| state.replaceable())
&& world
.get_block_state(&block_pos.down())
.await
.is_ok_and(|state| state.is_solid() && state.is_full_cube())
let down = world.get_block_state(&block_pos.down()).await;
world.get_block_state(&block_pos.up()).await.replaceable()
&& down.is_solid()
&& down.is_full_cube()
}

View File

@ -77,6 +77,6 @@ impl PumpkinBlock for FarmLandBlock {
}
async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
let state = world.get_block_state(&block_pos.up()).await.unwrap();
let state = world.get_block_state(&block_pos.up()).await;
!state.is_solid() // TODO: add fence gate block
}

View File

@ -22,7 +22,7 @@ use pumpkin_data::item::Item;
type FenceGateProperties = pumpkin_data::block_properties::OakFenceGateLikeProperties;
pub async fn toggle_fence_gate(world: &Arc<World>, block_pos: &BlockPos) -> BlockStateId {
let (block, state) = world.get_block_and_block_state(block_pos).await.unwrap();
let (block, state) = world.get_block_and_block_state(block_pos).await;
let mut fence_gate_props = FenceGateProperties::from_state_id(state.id, &block);
fence_gate_props.open = !fence_gate_props.open;

View File

@ -72,11 +72,8 @@ pub async fn compute_fence_state(
) -> u16 {
for direction in BlockDirection::horizontal() {
let other_block_pos = block_pos.offset(direction.to_offset());
let Ok((other_block, other_block_state)) =
world.get_block_and_block_state(&other_block_pos).await
else {
continue;
};
let (other_block, other_block_state) =
world.get_block_and_block_state(&other_block_pos).await;
let connected = connects_to(block, &other_block, &other_block_state, direction);
match direction {

View File

@ -104,7 +104,7 @@ impl PumpkinBlock for FireBlock {
_neighbor_pos: &BlockPos,
_neighbor_state: BlockStateId,
) -> BlockStateId {
if !FireBlockBase::can_place_on(&world.get_block(&block_pos.down()).await.unwrap()) {
if !FireBlockBase::can_place_on(&world.get_block(&block_pos.down()).await) {
return Block::AIR.default_state_id;
}

View File

@ -15,7 +15,7 @@ pub struct FireBlockBase;
impl FireBlockBase {
pub async fn get_fire_type(world: &World, pos: &BlockPos) -> Block {
let (block, _block_state) = world.get_block_and_block_state(&pos.down()).await.unwrap();
let (block, _block_state) = world.get_block_and_block_state(&pos.down()).await;
if SoulFireBlock::is_soul_base(&block) {
return Block::SOUL_FIRE;
}
@ -32,9 +32,8 @@ impl FireBlockBase {
}
pub async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
let block_state = world.get_block_state(block_pos).await.unwrap();
block_state.is_air()
&& Self::can_place_on(&world.get_block(&block_pos.down()).await.unwrap())
let block_state = world.get_block_state(block_pos).await;
block_state.is_air() && Self::can_place_on(&world.get_block(&block_pos.down()).await)
}
async fn broken(world: Arc<World>, block_pos: BlockPos) {

View File

@ -39,7 +39,7 @@ impl PumpkinBlock for SoulFireBlock {
_neighbor_pos: &BlockPos,
_neighbor_state: BlockStateId,
) -> BlockStateId {
if !Self::is_soul_base(&world.get_block(&block_pos.down()).await.unwrap()) {
if !Self::is_soul_base(&world.get_block(&block_pos.down()).await) {
return Block::AIR.default_state_id;
}
@ -57,7 +57,7 @@ impl PumpkinBlock for SoulFireBlock {
_use_item_on: &SUseItemOn,
) -> bool {
FireBlockBase::can_place_at(world, block_pos).await
&& Self::is_soul_base(&world.get_block(&block_pos.down()).await.unwrap())
&& Self::is_soul_base(&world.get_block(&block_pos.down()).await)
}
async fn broken(

View File

@ -70,11 +70,8 @@ pub async fn compute_pane_state(
) -> u16 {
for direction in BlockDirection::horizontal() {
let other_block_pos = block_pos.offset(direction.to_offset());
let Ok((other_block, other_block_state)) =
world.get_block_and_block_state(&other_block_pos).await
else {
continue;
};
let (other_block, other_block_state) =
world.get_block_and_block_state(&other_block_pos).await;
let connected = other_block == *block
|| (other_block_state.is_solid() && other_block_state.is_full_cube())

View File

@ -61,11 +61,8 @@ pub async fn compute_bars_state(
) -> u16 {
for direction in BlockDirection::horizontal() {
let other_block_pos = block_pos.offset(direction.to_offset());
let Ok((other_block, other_block_state)) =
world.get_block_and_block_state(&other_block_pos).await
else {
continue;
};
let (other_block, other_block_state) =
world.get_block_and_block_state(&other_block_pos).await;
let connected = other_block == *block
|| (other_block_state.is_solid() && other_block_state.is_full_cube())

View File

@ -22,11 +22,7 @@ pub struct JukeboxBlock;
impl JukeboxBlock {
async fn has_record(&self, block: &Block, location: BlockPos, world: &World) -> bool {
let state_id = world
.get_block_state(&location)
.await
.expect("`location` should be a jukebox")
.id;
let state_id = world.get_block_state(&location).await.id;
JukeboxLikeProperties::from_state_id(state_id, block).has_record
}

View File

@ -2,6 +2,7 @@ pub mod barrel;
pub mod bed;
pub mod cactus;
pub mod chest;
pub mod command;
pub mod crafting_table;
pub mod dirt_path;
pub mod doors;

View File

@ -29,9 +29,7 @@ pub struct NoteBlock;
impl NoteBlock {
pub async fn play_note(props: &NoteBlockLikeProperties, world: &World, pos: &BlockPos) {
if !is_base_block(props.instrument)
|| world.get_block_state(&pos.up()).await.unwrap().is_air()
{
if !is_base_block(props.instrument) || world.get_block_state(&pos.up()).await.is_air() {
world.add_synced_block_event(*pos, 0, 0).await;
}
}
@ -49,7 +47,6 @@ impl NoteBlock {
&world
.get_block_state(&pos.up())
.await
.unwrap()
.instrument
.to_lowercase(),
);
@ -62,7 +59,6 @@ impl NoteBlock {
&world
.get_block_state(&pos.down())
.await
.unwrap()
.instrument
.to_lowercase(),
);
@ -86,7 +82,7 @@ impl PumpkinBlock for NoteBlock {
_source_block: &Block,
_notify: bool,
) {
let block_state = world.get_block_state(pos).await.unwrap();
let block_state = world.get_block_state(pos).await;
let mut note_props = NoteBlockLikeProperties::from_state_id(block_state.id, block);
let powered = block_receives_redstone_power(world, pos).await;
// check if powered state changed
@ -109,7 +105,7 @@ impl PumpkinBlock for NoteBlock {
_server: &Server,
world: &Arc<World>,
) {
let block_state = world.get_block_state(&pos).await.unwrap();
let block_state = world.get_block_state(&pos).await;
let mut note_props = NoteBlockLikeProperties::from_state_id(block_state.id, block);
let next_index = note_props.note.to_index() + 1;
// Increment and check if max
@ -145,7 +141,7 @@ impl PumpkinBlock for NoteBlock {
_type: u8,
_data: u8,
) -> bool {
let block_state = world.get_block_state(pos).await.unwrap();
let block_state = world.get_block_state(pos).await;
let note_props = NoteBlockLikeProperties::from_state_id(block_state.id, block);
let instrument = note_props.instrument;
let pitch = if is_base_block(instrument) {

View File

@ -49,11 +49,7 @@ impl<'a> PistonHandler<'a> {
pub async fn calculate_push(&mut self) -> bool {
self.moved_blocks.clear();
self.broken_blocks.clear();
let (block, block_state) = self
.world
.get_block_and_block_state(&self.pos_to)
.await
.unwrap();
let (block, block_state) = self.world.get_block_and_block_state(&self.pos_to).await;
dbg!(PistonBlock::is_movable(
&block,
&block_state,
@ -78,7 +74,7 @@ impl<'a> PistonHandler<'a> {
return false;
}
for block_pos in self.moved_blocks.clone() {
let block = self.world.get_block(&block_pos).await.unwrap();
let block = self.world.get_block(&block_pos).await;
if Self::is_block_sticky(&block)
&& !self.try_move_adjacent_block(&block, block_pos).await
{
@ -103,8 +99,7 @@ impl<'a> PistonHandler<'a> {
}
async fn try_move(&mut self, pos: BlockPos, dir: BlockDirection) -> bool {
let (mut block, mut block_state) =
self.world.get_block_and_block_state(&pos).await.unwrap();
let (mut block, mut block_state) = self.world.get_block_and_block_state(&pos).await;
if block_state.is_air() {
return true;
}
@ -124,11 +119,7 @@ impl<'a> PistonHandler<'a> {
while Self::is_block_sticky(&block) {
let block_pos = pos.offset_dir(self.motion_direction.opposite().to_offset(), i as i32);
let block2 = block;
(block, block_state) = self
.world
.get_block_and_block_state(&block_pos)
.await
.unwrap();
(block, block_state) = self.world.get_block_and_block_state(&block_pos).await;
if block_state.is_air()
|| !Self::is_adjacent_block_stuck(&block2, &block)
|| !PistonBlock::is_movable(
@ -160,7 +151,7 @@ impl<'a> PistonHandler<'a> {
self.set_moved_blocks(j, l);
for m in 0..=(l + j) {
let block_pos3 = self.moved_blocks[m];
let block = self.world.get_block(&block_pos3).await.unwrap();
let block = self.world.get_block(&block_pos3).await;
if Self::is_block_sticky(&block)
&& !Box::pin(self.try_move_adjacent_block(&block, block_pos3)).await
{
@ -169,11 +160,7 @@ impl<'a> PistonHandler<'a> {
}
return true;
}
(block, block_state) = self
.world
.get_block_and_block_state(&block_pos2)
.await
.unwrap();
(block, block_state) = self.world.get_block_and_block_state(&block_pos2).await;
if block_state.is_air() {
return true;
}
@ -219,7 +206,7 @@ impl<'a> PistonHandler<'a> {
continue;
}
let block_pos = pos.offset(direction.to_offset());
let block_state2 = self.world.get_block(&block_pos).await.unwrap();
let block_state2 = self.world.get_block(&block_pos).await;
if Self::is_adjacent_block_stuck(&block_state2, block)
&& !self.try_move(block_pos, direction).await
{

View File

@ -142,7 +142,7 @@ impl PumpkinBlock for PistonBlock {
r#type: u8,
data: u8,
) -> bool {
let state = world.get_block_state(pos).await.unwrap();
let state = world.get_block_state(pos).await;
let mut props = PistonProps::from_state_id(state.id, block);
let dir = props.facing.to_block_direction();
@ -225,7 +225,7 @@ impl PumpkinBlock for PistonBlock {
world.update_neighbors(pos, None).await;
if sticky {
let pos = pos.offset_dir(dir.to_offset(), 2);
let (block, state) = world.get_block_and_block_state(&pos).await.unwrap();
let (block, state) = world.get_block_and_block_state(&pos).await;
let mut bl2 = false;
if block == Block::MOVING_PISTON {
if let Some(entity) = world.get_block_entity(&pos).await {
@ -273,10 +273,7 @@ impl PumpkinBlock for PistonBlock {
async fn should_extend(world: &World, block_pos: &BlockPos, piston_dir: BlockDirection) -> bool {
for dir in BlockDirection::all() {
let neighbor_pos = block_pos.offset(dir.to_offset());
let (block, state) = world
.get_block_and_block_state(&neighbor_pos)
.await
.unwrap();
let (block, state) = world.get_block_and_block_state(&neighbor_pos).await;
// Pistons can't be powered from the same direction as they are facing
if dir == piston_dir
|| !is_emitting_redstone_power(&block, &state, world, &neighbor_pos, dir).await
@ -286,19 +283,13 @@ async fn should_extend(world: &World, block_pos: &BlockPos, piston_dir: BlockDir
return true;
}
let neighbor_pos = block_pos.offset(BlockDirection::Down.to_offset());
let (block, state) = world
.get_block_and_block_state(&neighbor_pos)
.await
.unwrap();
let (block, state) = world.get_block_and_block_state(&neighbor_pos).await;
if is_emitting_redstone_power(&block, &state, world, block_pos, BlockDirection::Down).await {
return true;
}
for dir in BlockDirection::all() {
let neighbor_pos = block_pos.up().offset(dir.to_offset());
let (block, state) = world
.get_block_and_block_state(&neighbor_pos)
.await
.unwrap();
let (block, state) = world.get_block_and_block_state(&neighbor_pos).await;
if dir == BlockDirection::Down
|| !is_emitting_redstone_power(&block, &state, world, &neighbor_pos, dir).await
{
@ -310,7 +301,7 @@ async fn should_extend(world: &World, block_pos: &BlockPos, piston_dir: BlockDir
}
async fn try_move(world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let props = PistonProps::from_state_id(state.id, block);
let dir = props.facing.to_block_direction();
let should_extent = should_extend(world, block_pos, dir).await;
@ -326,7 +317,7 @@ async fn try_move(world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
}
} else if !should_extent && props.extended {
let new_pos = block_pos.offset_dir(dir.to_offset(), 2);
let (new_block, new_state) = world.get_block_and_block_state(&new_pos).await.unwrap();
let (new_block, new_state) = world.get_block_and_block_state(&new_pos).await;
let mut r#type = 1;
if new_block == Block::MOVING_PISTON {
@ -358,7 +349,7 @@ async fn move_piston(
sticky: bool,
) -> bool {
let extended_pos = block_pos.offset(dir.to_offset());
if !extend && world.get_block(&extended_pos).await.unwrap() == Block::PISTON_HEAD {
if !extend && world.get_block(&extended_pos).await == Block::PISTON_HEAD {
world
.set_block_state(
&extended_pos,
@ -379,7 +370,7 @@ async fn move_piston(
let mut moved_block_states: Vec<BlockState> = Vec::new();
for &block_pos in &moved_blocks {
let block_state = world.get_block_state(&block_pos).await.unwrap();
let block_state = world.get_block_state(&block_pos).await;
moved_block_states.push(block_state.clone());
moved_blocks_map.insert(block_pos, block_state);
}
@ -390,7 +381,7 @@ async fn move_piston(
let move_direction = if extend { dir } else { dir.opposite() };
for &broken_block_pos in broken_blocks.iter().rev() {
let block_state = world.get_block_state(&broken_block_pos).await.unwrap();
let block_state = world.get_block_state(&broken_block_pos).await;
world
.break_block(
&broken_block_pos,
@ -402,7 +393,7 @@ async fn move_piston(
}
for (index, &moved_block_pos) in moved_blocks.iter().rev().enumerate() {
let block_state = world.get_block_state(&moved_block_pos).await.unwrap();
let block_state = world.get_block_state(&moved_block_pos).await;
let target_pos = moved_block_pos.offset(move_direction.to_offset());
moved_blocks_map.remove(&target_pos);

View File

@ -34,7 +34,7 @@ impl PumpkinBlock for PistonExtensionBlock {
) {
let props = MovingPistonProps::from_state_id(state.id, &Block::MOVING_PISTON);
let pos = location.offset(props.facing.opposite().to_block_direction().to_offset());
let (new_block, new_state) = world.get_block_and_block_state(&pos).await.unwrap();
let (new_block, new_state) = world.get_block_and_block_state(&pos).await;
if PistonBlock::ids(&PistonBlock).contains(&new_block.name) {
let props = PistonProps::from_state_id(new_state.id, &new_block);
if props.extended {

View File

@ -34,7 +34,7 @@ impl PumpkinBlock for PistonHeadBlock {
) {
let props = PistonHeadProperties::from_state_id(state.id, &Block::PISTON_HEAD);
let pos = location.offset(props.facing.opposite().to_block_direction().to_offset());
let (new_block, new_state) = world.get_block_and_block_state(&pos).await.unwrap();
let (new_block, new_state) = world.get_block_and_block_state(&pos).await;
if PistonBlock::ids(&PistonBlock).contains(&new_block.name) {
let props = PistonProps::from_state_id(new_state.id, &new_block);
if props.extended {

View File

@ -26,7 +26,7 @@ use crate::server::Server;
use crate::world::World;
async fn click_button(world: &Arc<World>, block_pos: &BlockPos) {
let (block, state) = world.get_block_and_block_state(block_pos).await.unwrap();
let (block, state) = world.get_block_and_block_state(block_pos).await;
let mut button_props = ButtonLikeProperties::from_state_id(state.id, &block);
if !button_props.powered {
@ -113,7 +113,7 @@ impl PumpkinBlock for ButtonBlock {
}
async fn on_scheduled_tick(&self, world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let mut props = ButtonLikeProperties::from_state_id(state.id, block);
props.powered = false;
world

View File

@ -20,7 +20,7 @@ use crate::{
};
async fn toggle_lever(world: &Arc<World>, block_pos: &BlockPos) {
let (block, state) = world.get_block_and_block_state(block_pos).await.unwrap();
let (block, state) = world.get_block_and_block_state(block_pos).await;
let mut lever_props = LeverLikeProperties::from_state_id(state.id, &block);
lever_props.powered = !lever_props.powered;

View File

@ -26,7 +26,7 @@ pub mod turbo;
pub async fn update_wire_neighbors(world: &Arc<World>, pos: &BlockPos) {
for direction in BlockDirection::all() {
let neighbor_pos = pos.offset(direction.to_offset());
let block = world.get_block(&neighbor_pos).await.unwrap();
let block = world.get_block(&neighbor_pos).await;
world
.block_registry
.on_neighbor_update(world, &block, &neighbor_pos, &block, true)
@ -34,7 +34,7 @@ pub async fn update_wire_neighbors(world: &Arc<World>, pos: &BlockPos) {
for n_direction in BlockDirection::all() {
let n_neighbor_pos = neighbor_pos.offset(n_direction.to_offset());
let block = world.get_block(&n_neighbor_pos).await.unwrap();
let block = world.get_block(&n_neighbor_pos).await;
world
.block_registry
.on_neighbor_update(world, &block, &n_neighbor_pos, &block, true)
@ -90,8 +90,7 @@ async fn get_max_strong_power(world: &World, pos: &BlockPos, dust_power: bool) -
for side in BlockDirection::all() {
let (block, state) = world
.get_block_and_block_state(&pos.offset(side.to_offset()))
.await
.unwrap();
.await;
max_power = max_power.max(
get_strong_power(
&block,
@ -112,8 +111,7 @@ async fn get_max_weak_power(world: &World, pos: &BlockPos, dust_power: bool) ->
for side in BlockDirection::all() {
let (block, state) = world
.get_block_and_block_state(&pos.offset(side.to_offset()))
.await
.unwrap();
.await;
max_power = max_power.max(
get_weak_power(
&block,
@ -166,10 +164,7 @@ async fn get_strong_power(
pub async fn block_receives_redstone_power(world: &World, pos: &BlockPos) -> bool {
for face in BlockDirection::all() {
let neighbor_pos = pos.offset(face.to_offset());
let (block, state) = world
.get_block_and_block_state(&neighbor_pos)
.await
.unwrap();
let (block, state) = world.get_block_and_block_state(&neighbor_pos).await;
if is_emitting_redstone_power(&block, &state, world, pos, face).await {
return true;
}
@ -183,7 +178,7 @@ pub fn is_diode(block: &Block) -> bool {
pub async fn diode_get_input_strength(world: &World, pos: &BlockPos, facing: BlockDirection) -> u8 {
let input_pos = pos.offset(facing.to_offset());
let (input_block, input_state) = world.get_block_and_block_state(&input_pos).await.unwrap();
let (input_block, input_state) = world.get_block_and_block_state(&input_pos).await;
let power: u8 = get_redstone_power(&input_block, &input_state, world, &input_pos, facing).await;
if power == 0 && input_state.is_solid() {
return get_max_weak_power(world, &input_pos, true).await;

View File

@ -50,7 +50,7 @@ impl PumpkinBlock for ObserverBlock {
}
async fn on_scheduled_tick(&self, world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let mut props = ObserverLikeProperties::from_state_id(state.id, block);
if props.powered {

View File

@ -25,7 +25,7 @@ pub trait PressurePlate {
}
async fn on_scheduled_tick_pp(&self, world: &Arc<World>, block: &Block, pos: &BlockPos) {
let state = world.get_block_state(pos).await.unwrap();
let state = world.get_block_state(pos).await;
let output = self.get_redstone_output(block, state.id);
if output > 0 {
self.update_plate_state(world, *pos, block, state, output)

View File

@ -16,7 +16,7 @@ pub(super) async fn rail_placement_is_valid(world: &World, block: &Block, pos: &
return false;
}
let state_id = world.get_block_state_id(pos).await.unwrap();
let state_id = world.get_block_state_id(pos).await;
let rail_props = RailProperties::new(state_id, block);
let rail_leaning_direction = match rail_props.shape() {
RailShape::AscendingNorth => Some(HorizontalFacing::North),
@ -36,7 +36,7 @@ pub(super) async fn rail_placement_is_valid(world: &World, block: &Block, pos: &
}
pub(super) async fn can_place_rail_at(world: &World, pos: &BlockPos) -> bool {
let state = world.get_block_state(&pos.down()).await.unwrap();
let state = world.get_block_state(&pos.down()).await;
state.is_solid()
}

View File

@ -27,7 +27,7 @@ struct Rail {
impl Rail {
async fn find_with_elevation(world: &World, position: BlockPos) -> Option<Self> {
let (block, block_state) = world.get_block_and_block_state(&position).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(&position).await;
if block.is_tagged_with("#minecraft:rails").unwrap() {
let properties = RailProperties::new(block_state.id, &block);
return Some(Self {
@ -39,7 +39,7 @@ impl Rail {
}
let pos = position.up();
let (block, block_state) = world.get_block_and_block_state(&pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(&pos).await;
if block.is_tagged_with("#minecraft:rails").unwrap() {
let properties = RailProperties::new(block_state.id, &block);
return Some(Self {
@ -51,7 +51,7 @@ impl Rail {
}
let pos = position.down();
let (block, block_state) = world.get_block_and_block_state(&pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(&pos).await;
if block.is_tagged_with("#minecraft:rails").unwrap() {
let properties = RailProperties::new(block_state.id, &block);
return Some(Self {

View File

@ -43,7 +43,7 @@ impl PumpkinBlock for RedstoneLamp {
_source_block: &Block,
_notify: bool,
) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let mut props = RedstoneLampProperties::from_state_id(state.id, block);
let is_lit = props.lit;
let is_receiving_power = block_receives_redstone_power(world, block_pos).await;
@ -67,7 +67,7 @@ impl PumpkinBlock for RedstoneLamp {
}
async fn on_scheduled_tick(&self, world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let mut props = RedstoneLampProperties::from_state_id(state.id, block);
let is_lit = props.lit;
let is_receiving_power = block_receives_redstone_power(world, block_pos).await;

View File

@ -67,7 +67,7 @@ impl PumpkinBlock for RedstoneTorchBlock {
_source_block: &Block,
_notify: bool,
) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
if world.is_block_tick_scheduled(block_pos, block).await {
return;
@ -153,7 +153,7 @@ impl PumpkinBlock for RedstoneTorchBlock {
}
async fn on_scheduled_tick(&self, world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
if block == &Block::REDSTONE_WALL_TORCH {
let mut props = RWallTorchProps::from_state_id(state.id, block);
let should_be_lit_now = should_be_lit(
@ -208,7 +208,7 @@ impl PumpkinBlock for RedstoneTorchBlock {
pub async fn should_be_lit(world: &World, pos: &BlockPos, face: BlockDirection) -> bool {
let other_pos = pos.offset(face.to_offset());
let (block, state) = world.get_block_and_block_state(&other_pos).await.unwrap();
let (block, state) = world.get_block_and_block_state(&other_pos).await;
get_redstone_power(&block, &state, world, &other_pos, face).await == 0
}

View File

@ -132,11 +132,11 @@ impl PumpkinBlock for RedstoneWireBlock {
for direction in BlockDirection::horizontal() {
let other_block_pos = block_pos.offset(direction.to_offset());
let other_block = world.get_block(&other_block_pos).await.unwrap();
let other_block = world.get_block(&other_block_pos).await;
if wire_props.is_side_connected(direction) && other_block != Block::REDSTONE_WIRE {
let up_block_pos = other_block_pos.up();
let up_block = world.get_block(&up_block_pos).await.unwrap();
let up_block = world.get_block(&up_block_pos).await;
if up_block == Block::REDSTONE_WIRE {
world
.replace_with_state_for_neighbor_update(
@ -148,7 +148,7 @@ impl PumpkinBlock for RedstoneWireBlock {
}
let down_block_pos = other_block_pos.down();
let down_block = world.get_block(&down_block_pos).await.unwrap();
let down_block = world.get_block(&down_block_pos).await;
if down_block == Block::REDSTONE_WIRE {
world
.replace_with_state_for_neighbor_update(
@ -170,7 +170,7 @@ impl PumpkinBlock for RedstoneWireBlock {
_server: &Server,
world: &Arc<World>,
) {
let state = world.get_block_state(&location).await.unwrap();
let state = world.get_block_state(&location).await;
let wire = RedstoneWireProperties::from_state_id(state.id, block);
on_use(wire, world, &location).await;
}
@ -184,7 +184,7 @@ impl PumpkinBlock for RedstoneWireBlock {
_server: &Server,
world: &Arc<World>,
) -> BlockActionResult {
let state = world.get_block_state(&location).await.unwrap();
let state = world.get_block_state(&location).await;
let wire = RedstoneWireProperties::from_state_id(state.id, block);
if on_use(wire, world, &location).await {
BlockActionResult::Consume
@ -202,7 +202,7 @@ impl PumpkinBlock for RedstoneWireBlock {
_notify: bool,
) {
if can_place_at(world, pos).await {
let state = world.get_block_state(pos).await.unwrap();
let state = world.get_block_state(pos).await;
let mut wire = RedstoneWireProperties::from_state_id(state.id, block);
let new_power = calculate_power(world, pos).await;
if wire.power.to_index() as u8 != new_power {
@ -279,7 +279,7 @@ impl PumpkinBlock for RedstoneWireBlock {
}
async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
let floor = world.get_block_state(&block_pos.down()).await.unwrap();
let floor = world.get_block_state(&block_pos.down()).await;
// TODO: Only check face instead of block
floor.is_full_cube()
}
@ -351,24 +351,20 @@ fn can_connect_diagonal_to(block: &Block) -> bool {
pub async fn get_side(world: &World, pos: &BlockPos, side: BlockDirection) -> WireConnection {
let neighbor_pos: BlockPos = pos.offset(side.to_offset());
let (neighbor, state) = world
.get_block_and_block_state(&neighbor_pos)
.await
.unwrap();
let (neighbor, state) = world.get_block_and_block_state(&neighbor_pos).await;
if can_connect_to(world, &neighbor, side, &state).await {
return WireConnection::Side;
}
let up_pos = pos.offset(BlockDirection::Up.to_offset());
let up_state = world.get_block_state(&up_pos).await.unwrap();
let up_state = world.get_block_state(&up_pos).await;
if !up_state.is_solid()
&& can_connect_diagonal_to(
&world
.get_block(&neighbor_pos.offset(BlockDirection::Up.to_offset()))
.await
.unwrap(),
.await,
)
{
WireConnection::Up
@ -376,8 +372,7 @@ pub async fn get_side(world: &World, pos: &BlockPos, side: BlockDirection) -> Wi
&& can_connect_diagonal_to(
&world
.get_block(&neighbor_pos.offset(BlockDirection::Down.to_offset()))
.await
.unwrap(),
.await,
)
{
WireConnection::Side
@ -581,7 +576,7 @@ impl CardinalWireConnectionExt for WestWireConnection {
}
async fn max_wire_power(wire_power: u8, world: &World, pos: BlockPos) -> u8 {
let (block, block_state) = world.get_block_and_block_state(&pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(&pos).await;
if block == Block::REDSTONE_WIRE {
let wire = RedstoneWireProperties::from_state_id(block_state.id, &block);
wire_power.max(wire.power.to_index() as u8)
@ -595,15 +590,12 @@ async fn calculate_power(world: &World, pos: &BlockPos) -> u8 {
let mut wire_power: u8 = 0;
let up_pos = pos.offset(BlockDirection::Up.to_offset());
let (_up_block, up_state) = world.get_block_and_block_state(&up_pos).await.unwrap();
let (_up_block, up_state) = world.get_block_and_block_state(&up_pos).await;
for side in BlockDirection::all() {
let neighbor_pos = pos.offset(side.to_offset());
wire_power = max_wire_power(wire_power, world, neighbor_pos).await;
let (neighbor, neighbor_state) = world
.get_block_and_block_state(&neighbor_pos)
.await
.unwrap();
let (neighbor, neighbor_state) = world.get_block_and_block_state(&neighbor_pos).await;
block_power = block_power.max(
get_redstone_power_no_dust(&neighbor, &neighbor_state, world, neighbor_pos, side).await,
);

View File

@ -66,7 +66,7 @@ impl PumpkinBlock for RepeaterBlock {
_source_block: &Block,
_notify: bool,
) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let mut rep = RepeaterProperties::from_state_id(state.id, block);
let should_be_locked = should_be_locked(&rep.facing, world, block_pos).await;
if !rep.locked && should_be_locked {
@ -90,7 +90,7 @@ impl PumpkinBlock for RepeaterBlock {
}
async fn on_scheduled_tick(&self, world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
let state = world.get_block_state(block_pos).await.unwrap();
let state = world.get_block_state(block_pos).await;
let mut rep = RepeaterProperties::from_state_id(state.id, block);
if rep.locked {
return;
@ -120,7 +120,7 @@ impl PumpkinBlock for RepeaterBlock {
_server: &Server,
world: &Arc<World>,
) {
let state = world.get_block_state(&location).await.unwrap();
let state = world.get_block_state(&location).await;
let props = RepeaterProperties::from_state_id(state.id, block);
on_use(props, world, location, block).await;
}
@ -134,7 +134,7 @@ impl PumpkinBlock for RepeaterBlock {
_server: &Server,
world: &Arc<World>,
) -> BlockActionResult {
let state = world.get_block_state(&location).await.unwrap();
let state = world.get_block_state(&location).await;
let props = RepeaterProperties::from_state_id(state.id, block);
on_use(props, world, location, block).await;
BlockActionResult::Consume
@ -204,7 +204,7 @@ async fn should_be_locked(facing: &HorizontalFacing, world: &World, pos: &BlockP
async fn get_power_on_side(world: &World, pos: &BlockPos, side: HorizontalFacing) -> u8 {
let side_pos = pos.offset(side.to_block_direction().to_offset());
let (side_block, side_state) = world.get_block_and_block_state(&side_pos).await.unwrap();
let (side_block, side_state) = world.get_block_and_block_state(&side_pos).await;
if is_diode(&side_block) {
get_weak_power(
&side_block,
@ -222,12 +222,12 @@ async fn get_power_on_side(world: &World, pos: &BlockPos, side: HorizontalFacing
async fn on_state_change(rep: RepeaterProperties, world: &Arc<World>, pos: &BlockPos) {
let front_pos = pos.offset(rep.facing.opposite().to_block_direction().to_offset());
let front_block = world.get_block(&front_pos).await.unwrap();
let front_block = world.get_block(&front_pos).await;
world.update_neighbor(&front_pos, &front_block).await;
for direction in BlockDirection::all() {
let neighbor_pos = front_pos.offset(direction.to_offset());
let block = world.get_block(&neighbor_pos).await.unwrap();
let block = world.get_block(&neighbor_pos).await;
world.update_neighbor(&neighbor_pos, &block).await;
}
}
@ -240,8 +240,7 @@ async fn schedule_tick(
) {
let front_block = world
.get_block(&pos.offset(rep.facing.opposite().to_block_direction().to_offset()))
.await
.unwrap();
.await;
let priority = if is_diode(&front_block) {
TickPriority::ExtremelyHigh
} else if !should_be_powered {

View File

@ -4,7 +4,10 @@
use pumpkin_data::{
Block, BlockState,
block_properties::{BlockProperties, EnumVariants, Integer0To15, RedstoneWireLikeProperties},
block_properties::{
BlockProperties, EnumVariants, Integer0To15, RedstoneWireLikeProperties,
get_state_by_state_id,
},
};
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
use pumpkin_world::{block::BlockDirection, world::BlockFlags};
@ -42,7 +45,7 @@ impl UpdateNode {
async fn new(world: &World, pos: BlockPos) -> Self {
Self {
pos,
state: world.get_block_state(&pos).await.unwrap(),
state: world.get_block_state(&pos).await,
visited: false,
neighbors: None,
xbias: 0,
@ -329,9 +332,7 @@ impl RedstoneWireTurbo {
let node = &mut self.nodes[upd1.index];
let mut wire = unwrap_wire(&node.state);
wire.power = new_wire.power;
node.state = world
.get_state_by_id(wire.to_state_id(&Block::REDSTONE_WIRE))
.unwrap();
node.state = get_state_by_state_id(wire.to_state_id(&Block::REDSTONE_WIRE)).unwrap();
self.propagate_changes(world, upd1, layer).await;
}

View File

@ -77,7 +77,7 @@ impl PumpkinBlock for StairBlock {
_source_block: &Block,
_notify: bool,
) {
let state_id = world.get_block_state_id(block_pos).await.unwrap();
let state_id = world.get_block_state_id(block_pos).await;
let mut stair_props = StairsProperties::from_state_id(state_id, block);
let new_shape =
@ -158,7 +158,7 @@ async fn get_stair_properties_if_exists(
world: &World,
block_pos: &BlockPos,
) -> Option<StairsProperties> {
let (block, block_state) = world.get_block_and_block_state(block_pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(block_pos).await;
block
.is_tagged_with("#minecraft:stairs")
.unwrap()

View File

@ -32,12 +32,8 @@ impl PumpkinBlock for SugarCaneBlock {
}
async fn random_tick(&self, block: &Block, world: &Arc<World>, pos: &BlockPos) {
if world.get_block_state(&pos.up()).await.unwrap().is_air() {
let state_id = world
.get_block_state(pos)
.await
.expect("`location` should be a sugar cane")
.id;
if world.get_block_state(&pos.up()).await.is_air() {
let state_id = world.get_block_state(pos).await.id;
let age = CactusLikeProperties::from_state_id(state_id, block).age;
if age == Integer0To15::L15 {
world
@ -93,7 +89,7 @@ impl PumpkinBlock for SugarCaneBlock {
}
async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
let block_below = world.get_block(&block_pos.down()).await.unwrap();
let block_below = world.get_block(&block_pos.down()).await;
if block_below == Block::SUGAR_CANE {
return true;
@ -105,8 +101,7 @@ async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool {
for direction in HorizontalFacing::all() {
let block = world
.get_block(&block_pos.down().offset(direction.to_offset()))
.await
.unwrap();
.await;
if block == Block::WATER || block == Block::FROSTED_ICE {
return true;

View File

@ -21,7 +21,7 @@ use std::sync::Arc;
type TrapDoorProperties = pumpkin_data::block_properties::OakTrapdoorLikeProperties;
async fn toggle_trapdoor(world: &Arc<World>, block_pos: &BlockPos) {
let (block, block_state) = world.get_block_and_block_state(block_pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(block_pos).await;
let mut trapdoor_props = TrapDoorProperties::from_state_id(block_state.id, &block);
trapdoor_props.open = !trapdoor_props.open;
@ -147,7 +147,7 @@ impl PumpkinBlock for TrapDoorBlock {
_source_block: &Block,
_notify: bool,
) {
let block_state = world.get_block_state(pos).await.unwrap();
let block_state = world.get_block_state(pos).await;
let mut trapdoor_props = TrapDoorProperties::from_state_id(block_state.id, block);
let powered = block_receives_redstone_power(world, pos).await;
if powered != trapdoor_props.powered {

View File

@ -75,18 +75,12 @@ pub async fn compute_wall_state(
block: &Block,
block_pos: &BlockPos,
) -> u16 {
let (block_above, block_above_state) = world
.get_block_and_block_state(&block_pos.up())
.await
.unwrap();
let (block_above, block_above_state) = world.get_block_and_block_state(&block_pos.up()).await;
for direction in HorizontalFacing::all() {
let other_block_pos = block_pos.offset(direction.to_offset());
let Ok((other_block, other_block_state)) =
world.get_block_and_block_state(&other_block_pos).await
else {
continue;
};
let (other_block, other_block_state) =
world.get_block_and_block_state(&other_block_pos).await;
let connected = other_block == *block
|| (other_block_state.is_solid() && other_block_state.is_full_cube())

View File

@ -87,9 +87,7 @@ pub trait FlowingFluid {
}
async fn spread_fluid(&self, world: &Arc<World>, fluid: &Fluid, block_pos: &BlockPos) {
let Ok(block_state_id) = world.get_block_state_id(block_pos).await else {
return;
};
let block_state_id = world.get_block_state_id(block_pos).await;
if let Some(new_fluid_state) = self.get_new_liquid(world, fluid, block_pos).await {
if new_fluid_state.to_state_id(fluid) != block_state_id {
world
@ -147,9 +145,7 @@ pub trait FlowingFluid {
fluid: &Fluid,
block_pos: &BlockPos,
) -> Option<FlowingFluidProperties> {
let Ok(current_state_id) = world.get_block_state_id(block_pos).await else {
return None;
};
let current_state_id = world.get_block_state_id(block_pos).await;
let current_props = FlowingFluidProperties::from_state_id(current_state_id, fluid);
let current_level = i32::from(current_props.level.to_index()) + 1;
@ -161,9 +157,7 @@ pub trait FlowingFluid {
for direction in BlockDirection::horizontal() {
let neighbor_pos = block_pos.offset(direction.to_offset());
let Ok(neighbor_state_id) = world.get_block_state_id(&neighbor_pos).await else {
continue;
};
let neighbor_state_id = world.get_block_state_id(&neighbor_pos).await;
if !self.is_same_fluid(fluid, neighbor_state_id) {
continue;
@ -181,9 +175,7 @@ pub trait FlowingFluid {
if source_count >= 2 && self.can_convert_to_source(world).await {
let below_pos = block_pos.down();
let Ok(below_state_id) = world.get_block_state_id(&below_pos).await else {
return Some(current_props);
};
let below_state_id = world.get_block_state_id(&below_pos).await;
if self
.is_solid_or_source(world, &below_pos, below_state_id, fluid)
.await
@ -193,9 +185,7 @@ pub trait FlowingFluid {
}
let above_pos = block_pos.up();
let Ok(above_state_id) = world.get_block_state_id(&above_pos).await else {
return Some(current_props);
};
let above_state_id = world.get_block_state_id(&above_pos).await;
if self.is_same_fluid(fluid, above_state_id) {
return Some(self.get_flowing(fluid, Level::L8, true).await);
@ -223,9 +213,7 @@ pub trait FlowingFluid {
state_id: BlockStateId,
fluid: &Fluid,
) -> bool {
let Ok(block) = world.get_block(block_pos).await else {
return false;
};
let block = world.get_block(block_pos).await;
if block.id != 0 && !self.can_be_replaced(world, block_pos, block.id).await {
return true;
@ -240,9 +228,7 @@ pub trait FlowingFluid {
}
async fn spread_to_sides(&self, world: &Arc<World>, fluid: &Fluid, block_pos: &BlockPos) {
let Ok(block_state_id) = world.get_block_state_id(block_pos).await else {
return;
};
let block_state_id = world.get_block_state_id(block_pos).await;
let props = FlowingFluidProperties::from_state_id(block_state_id, fluid);
let level = i32::from(props.level.to_index()) + 1;
@ -286,9 +272,7 @@ pub trait FlowingFluid {
let mut ctx = None;
for direction in BlockDirection::horizontal() {
let side_pos = block_pos.offset(direction.to_offset());
let Ok(side_state_id) = world.get_block_state_id(&side_pos).await else {
continue;
};
let side_state_id = world.get_block_state_id(&side_pos).await;
let side_props = FlowingFluidProperties::from_state_id(side_state_id, fluid);
@ -349,9 +333,7 @@ pub trait FlowingFluid {
continue;
}
let Ok(next_state_id) = world.get_block_state_id(&next_pos).await else {
continue;
};
let next_state_id = world.get_block_state_id(&next_pos).await;
if self.is_same_fluid(fluid, next_state_id) {
let next_props = FlowingFluidProperties::from_state_id(next_state_id, fluid);
@ -395,9 +377,7 @@ pub trait FlowingFluid {
}
async fn can_pass_through(&self, world: &Arc<World>, fluid: &Fluid, pos: &BlockPos) -> bool {
let Ok(state_id) = world.get_block_state_id(pos).await else {
return false;
};
let state_id = world.get_block_state_id(pos).await;
if self.is_same_fluid(fluid, state_id) {
return true;
@ -407,9 +387,7 @@ pub trait FlowingFluid {
}
async fn can_replace_block(&self, world: &Arc<World>, pos: &BlockPos, _fluid: &Fluid) -> bool {
let Ok(block) = world.get_block(pos).await else {
return false;
};
let block = world.get_block(pos).await;
if self.can_be_replaced(world, pos, block.id).await {
return true;
@ -419,9 +397,7 @@ pub trait FlowingFluid {
}
async fn can_be_replaced(&self, world: &Arc<World>, pos: &BlockPos, block_id: BlockId) -> bool {
let Ok(block_state_id) = world.get_block_state_id(pos).await else {
return false;
};
let block_state_id = world.get_block_state_id(pos).await;
if let Some(fluid) = Fluid::from_state_id(block_state_id) {
if fluid.is_source(block_state_id) && fluid.is_falling(block_state_id) {
@ -440,9 +416,7 @@ pub trait FlowingFluid {
_pos: &BlockPos,
below_pos: &BlockPos,
) -> bool {
let Ok(below_state_id) = world.get_block_state_id(below_pos).await else {
return false;
};
let below_state_id = world.get_block_state_id(below_pos).await;
if self.is_same_fluid(fluid, below_state_id) {
return true;

View File

@ -1,6 +1,7 @@
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::farmland::FarmLandBlock;
@ -100,6 +101,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
manager.register(NetherPortalBlock);
manager.register(NoteBlock);
manager.register(PumpkinBlock);
manager.register(CommandBlock);
manager.register(PressurePlateBlock);
manager.register(WeightedPressurePlateBlock);

View File

@ -299,10 +299,10 @@ impl BlockRegistry {
block: &Block,
flags: BlockFlags,
) {
let state = world.get_block_state(location).await.unwrap();
let state = world.get_block_state(location).await;
for direction in BlockDirection::all() {
let neighbor_pos = location.offset(direction.to_offset());
let neighbor_state = world.get_block_state(&neighbor_pos).await.unwrap();
let neighbor_state = world.get_block_state(&neighbor_pos).await;
let pumpkin_block = self.get_pumpkin_block(block);
if let Some(pumpkin_block) = pumpkin_block {
let new_state = pumpkin_block

View File

@ -112,18 +112,16 @@ impl CommandExecutor for Executor {
for y in start_y..=end_y {
for z in start_z..=end_z {
let block_position = BlockPos(Vector3 { x, y, z });
match world.get_block_state(&block_position).await {
Ok(old_state) if old_state.is_air() => {
world
.set_block_state(
&block_position,
block_state_id,
BlockFlags::FORCE_STATE,
)
.await;
placed_blocks += 1;
}
_ => {}
let old_state = world.get_block_state(&block_position).await;
if old_state.is_air() {
world
.set_block_state(
&block_position,
block_state_id,
BlockFlags::FORCE_STATE,
)
.await;
placed_blocks += 1;
}
}
}

View File

@ -73,8 +73,9 @@ impl CommandExecutor for Executor {
.await;
true
}
Mode::Keep => match world.get_block_state(&pos).await {
Ok(old_state) if old_state.is_air() => {
Mode::Keep => {
let old_state = world.get_block_state(&pos).await;
if old_state.is_air() {
world
.set_block_state(
&pos,
@ -83,10 +84,10 @@ impl CommandExecutor for Executor {
)
.await;
true
} else {
false
}
Ok(_) => false,
Err(e) => return Err(CommandError::OtherPumpkin(e.into())),
},
}
};
sender

View File

@ -200,10 +200,7 @@ impl LivingEntity {
pub async fn is_in_water(&self) -> bool {
let world = self.entity.world.read().await;
let block_pos = self.entity.block_pos.load();
world
.get_block(&block_pos)
.await
.is_ok_and(|block| block == Block::WATER)
world.get_block(&block_pos).await == Block::WATER
}
pub async fn update_fall_distance(

View File

@ -590,12 +590,11 @@ impl Entity {
for y in blockpos.0.y..=blockpos1.0.y {
for z in blockpos.0.z..=blockpos1.0.z {
let pos = BlockPos::new(x, y, z);
if let Ok((block, state)) = world.get_block_and_block_state(&pos).await {
world
.block_registry
.on_entity_collision(block, &world, entity, pos, state, server)
.await;
}
let (block, state) = world.get_block_and_block_state(&pos).await;
world
.block_registry
.on_entity_collision(block, &world, entity, pos, state, server)
.await;
if let Ok(fluid) = world.get_fluid(&pos).await {
world
.block_registry

View File

@ -57,10 +57,6 @@ use pumpkin_inventory::{
use pumpkin_macros::send_cancellable;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_nbt::tag::NbtTag;
use pumpkin_protocol::client::play::{
CCloseContainer, CEntityPositionSync, COpenScreen, CSetContainerContent, CSetContainerProperty,
CSetContainerSlot, CSetCursorItem, CSetPlayerInventory, PlayerInfoFlags, PreviousMessage,
};
use pumpkin_protocol::{
IdOr, RawPacket, ServerPacket,
client::play::{
@ -91,6 +87,14 @@ use pumpkin_protocol::{
client::play::Metadata,
server::play::{SClickSlot, SKeepAlive},
};
use pumpkin_protocol::{
client::play::{
CCloseContainer, CEntityPositionSync, COpenScreen, CSetContainerContent,
CSetContainerProperty, CSetContainerSlot, CSetCursorItem, CSetPlayerInventory,
PlayerInfoFlags, PreviousMessage,
},
server::play::SSetCommandBlock,
};
use pumpkin_util::{
GameMode,
math::{
@ -641,8 +645,8 @@ impl Player {
if self.mining.load(Relaxed) {
let pos = self.mining_pos.lock().await;
let world = self.world().await;
let block = world.get_block(&pos).await.unwrap();
let state = world.get_block_state(&pos).await.unwrap();
let block = world.get_block(&pos).await;
let state = world.get_block_state(&pos).await;
// Is the block broken?
if state.is_air() {
world
@ -1937,6 +1941,10 @@ impl Player {
.handle_player_action(SPlayerAction::read(payload)?, server)
.await;
}
SSetCommandBlock::PACKET_ID => {
self.handle_set_command_block(SSetCommandBlock::read(payload)?)
.await;
}
SPlayerCommand::PACKET_ID => {
self.handle_player_command(SPlayerCommand::read(payload)?)
.await;

View File

@ -50,7 +50,7 @@ impl PumpkinItem for AxeItem {
let new_block = Block::from_id(replacement_block.unwrap());
let new_block = &new_block.unwrap();
let new_state_id = if block.is_tagged_with("#minecraft:logs") == Some(true) {
let log_information = world.get_block_state_id(&location).await.unwrap();
let log_information = world.get_block_state_id(&location).await;
let log_props = PaleOakWoodLikeProperties::from_state_id(log_information, block);
// create new properties for the new log.
let mut new_log_properties = PaleOakWoodLikeProperties::default(new_block);
@ -65,7 +65,7 @@ impl PumpkinItem for AxeItem {
// Let's check if It's a door
else if block.is_tagged_with("#minecraft:doors") == Some(true) {
// get block state of the old log.
let door_information = world.get_block_state_id(&location).await.unwrap();
let door_information = world.get_block_state_id(&location).await;
// get the log properties
let door_props = OakDoorLikeProperties::from_state_id(door_information, block);
// create new properties for the new log.

View File

@ -60,15 +60,12 @@ fn get_start_and_end_pos(player: &Player) -> (Vector3<f64>, Vector3<f64>) {
#[async_trait]
impl PumpkinItem for EmptyBucketItem {
#[allow(clippy::too_many_lines)]
async fn normal_use(&self, _item: &Item, player: &Player) {
let world = player.world().await.clone();
let (start_pos, end_pos) = get_start_and_end_pos(player);
let checker = async |pos: &BlockPos, world_inner: &Arc<World>| {
let Ok(state_id) = world_inner.get_block_state_id(pos).await else {
return false;
};
let state_id = world_inner.get_block_state_id(pos).await;
state_id == Block::WATER.default_state_id || state_id == Block::LAVA.default_state_id
};
@ -76,10 +73,6 @@ impl PumpkinItem for EmptyBucketItem {
let (block_pos, _) = world.raytrace(start_pos, end_pos, checker).await;
if let Some(pos) = block_pos {
let Ok(_state_id) = world.get_block_state_id(&pos).await else {
return;
};
world
.set_block_state(&pos, Block::AIR.id, BlockFlags::NOTIFY_NEIGHBORS)
.await;
@ -99,9 +92,7 @@ impl PumpkinItem for FilledBucketItem {
let world = player.world().await.clone();
let (start_pos, end_pos) = get_start_and_end_pos(player);
let checker = async |pos: &BlockPos, world_inner: &Arc<World>| {
let Ok(state_id) = world_inner.get_block_state_id(pos).await else {
return false;
};
let state_id = world_inner.get_block_state_id(pos).await;
if Fluid::from_state_id(state_id).is_some() {
return false;
}

View File

@ -61,11 +61,7 @@ impl PumpkinItem for HoeItem {
if (block == &Block::GRASS_BLOCK
|| block == &Block::DIRT_PATH
|| block == &Block::DIRT)
&& world
.get_block_state(&location.up())
.await
.unwrap()
.is_air()
&& world.get_block_state(&location.up()).await.is_air()
{
future_block = &Block::FARMLAND;
}

View File

@ -45,7 +45,7 @@ impl PumpkinItem for HoneyCombItem {
&& block.is_tagged_with("#minecraft:doors").unwrap()
{
// get block state of the old log.
let door_information = world.get_block_state_id(&location).await.unwrap();
let door_information = world.get_block_state_id(&location).await;
// get the log properties
let door_props = OakDoorLikeProperties::from_state_id(door_information, block);
// create new properties for the new log.

View File

@ -46,12 +46,7 @@ impl PumpkinItem for ShovelItem {
|| block == &Block::MYCELIUM
{
let world = player.world().await;
if face != BlockDirection::Down
&& world
.get_block_state(&location.up())
.await
.unwrap()
.is_air()
if face != BlockDirection::Down && world.get_block_state(&location.up()).await.is_air()
{
world
.set_block_state(

View File

@ -3,6 +3,8 @@ use pumpkin_data::item::Item;
use pumpkin_inventory::InventoryError;
use pumpkin_inventory::equipment_slot::EquipmentSlot;
use pumpkin_inventory::screen_handler::ScreenHandler;
use pumpkin_world::block::entities::BlockEntity;
use pumpkin_world::block::entities::command_block::CommandBlockEntity;
use pumpkin_world::world::BlockFlags;
use rsa::pkcs1v15::{Signature as RsaPkcs1v15Signature, VerifyingKey};
use rsa::signature::Verifier;
@ -47,7 +49,8 @@ use pumpkin_protocol::client::play::{
};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::server::play::{
FLAG_ON_GROUND, SChunkBatch, SCookieResponse as SPCookieResponse, SPlayerSession, SUpdateSign,
CommandBlockMode, FLAG_ON_GROUND, SChunkBatch, SCookieResponse as SPCookieResponse,
SPlayerSession, SSetCommandBlock, SUpdateSign,
};
use pumpkin_protocol::{
client::play::{
@ -86,7 +89,6 @@ pub enum BlockPlacingError {
InvalidBlockFace,
BlockOutOfWorld,
InvalidGamemode,
NoBaseBlock,
}
impl std::fmt::Display for BlockPlacingError {
@ -99,13 +101,13 @@ impl PumpkinError for BlockPlacingError {
fn is_kick(&self) -> bool {
match self {
Self::BlockOutOfReach | Self::BlockOutOfWorld | Self::InvalidGamemode => false,
Self::InvalidBlockFace | Self::NoBaseBlock => true,
Self::InvalidBlockFace => true,
}
}
fn severity(&self) -> log::Level {
match self {
Self::BlockOutOfWorld | Self::InvalidGamemode | Self::NoBaseBlock => log::Level::Trace,
Self::BlockOutOfWorld | Self::InvalidGamemode => log::Level::Trace,
Self::BlockOutOfReach | Self::InvalidBlockFace => log::Level::Warn,
}
}
@ -114,7 +116,6 @@ impl PumpkinError for BlockPlacingError {
match self {
Self::BlockOutOfReach | Self::BlockOutOfWorld | Self::InvalidGamemode => None,
Self::InvalidBlockFace => Some("Invalid block face".into()),
Self::NoBaseBlock => Some("No base block".into()),
}
}
}
@ -565,9 +566,7 @@ impl Player {
}
let world = self.world().await;
let Ok(block) = world.get_block(&pick_item.pos).await else {
return;
};
let block = world.get_block(&pick_item.pos).await;
if block.item_id == 0 {
// Invalid block id (blocks such as tall seagrass)
@ -606,6 +605,33 @@ impl Player {
// // TODO: Implement and merge any redundant code with pick_item_from_block
// }
pub async fn handle_set_command_block(&self, command: SSetCommandBlock) {
// TODO: check things
let pos = command.pos;
if let Some((nbt, block_entity)) = self.world().await.get_block_entity(&pos).await {
let command_entity = CommandBlockEntity::from_nbt(&nbt, pos);
if block_entity.identifier() != command_entity.identifier() {
log::warn!(
"Client tried to change Command block but not Command block entity found"
);
return;
}
let Ok(command_block_mode) = CommandBlockMode::try_from(command.mode) else {
self.kick(TextComponent::text("Invalid Command block mode"))
.await;
return;
};
let _block_state = match command_block_mode {
CommandBlockMode::Chain => Block::CHAIN_COMMAND_BLOCK,
CommandBlockMode::Repeating => Block::REPEATING_COMMAND_BLOCK,
CommandBlockMode::Impulse => Block::COMMAND_BLOCK,
};
}
}
pub async fn handle_player_command(&self, command: SPlayerCommand) {
if command.entity_id != self.entity_id().into() {
return;
@ -1099,8 +1125,7 @@ impl Player {
let location = player_action.location;
let entity = &self.living_entity.entity;
let world = &entity.world.read().await;
let block = world.get_block(&location).await.unwrap();
let state = world.get_block_state(&location).await.unwrap();
let (block, state) = world.get_block_and_block_state(&location).await;
let inventory = self.inventory();
let held = inventory.held_item();
@ -1119,8 +1144,6 @@ impl Player {
// TODO: Config
if self.gamemode.load() == GameMode::Creative {
// Block break & play sound
let broken_state = world.get_block_state(&location).await.unwrap();
world
.break_block(
&location,
@ -1130,14 +1153,7 @@ impl Player {
.await;
server
.block_registry
.broken(
Arc::clone(world),
&block,
self,
location,
server,
broken_state,
)
.broken(Arc::clone(world), &block, self, location, server, state)
.await;
self.update_sequence(player_action.sequence.0);
return;
@ -1150,7 +1166,7 @@ impl Player {
let speed = block::calc_block_breaking(self, &state, block.name).await;
// Instant break
if speed >= 1.0 {
let broken_state = world.get_block_state(&location).await.unwrap();
let broken_state = world.get_block_state(&location).await;
world
.break_block(
&location,
@ -1219,27 +1235,26 @@ impl Player {
.store(false, std::sync::atomic::Ordering::Relaxed);
world.set_block_breaking(entity, location, -1).await;
if let Ok((block, state)) = world.get_block_and_block_state(&location).await {
let drop = self.gamemode.load() != GameMode::Creative
&& self.can_harvest(&state, block.name).await;
let (block, state) = world.get_block_and_block_state(&location).await;
let drop = self.gamemode.load() != GameMode::Creative
&& self.can_harvest(&state, block.name).await;
world
.break_block(
&location,
Some(self.clone()),
if drop {
BlockFlags::NOTIFY_NEIGHBORS
} else {
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
},
)
.await;
world
.break_block(
&location,
Some(self.clone()),
if drop {
BlockFlags::NOTIFY_NEIGHBORS
} else {
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
},
)
.await;
server
.block_registry
.broken(Arc::clone(world), &block, self, location, server, state)
.await;
}
server
.block_registry
.broken(Arc::clone(world), &block, self, location, server, state)
.await;
self.update_sequence(player_action.sequence.0);
}
@ -1329,9 +1344,7 @@ impl Player {
let entity = &self.living_entity.entity;
let world = &entity.world.read().await;
let Ok(block) = world.get_block(&location).await else {
return Err(BlockPlacingError::NoBaseBlock.into());
};
let block = world.get_block(&location).await;
let sneaking = self
.living_entity
@ -1593,7 +1606,7 @@ impl Player {
let clicked_block_pos = BlockPos(location.0);
let (clicked_block, clicked_block_state) =
world.get_block_and_block_state(&clicked_block_pos).await?;
world.get_block_and_block_state(&clicked_block_pos).await;
let replace_clicked_block = if clicked_block == block {
world
@ -1626,7 +1639,7 @@ impl Player {
} else {
let block_pos = BlockPos(location.0 + face.to_offset());
let (previous_block, previous_block_state) =
world.get_block_and_block_state(&block_pos).await?;
world.get_block_and_block_state(&block_pos).await;
let replace_previous_block = if previous_block == block {
world

View File

@ -41,8 +41,7 @@ impl Explosion {
let mut h = self.power * (0.7 + rand::random::<f32>() * 0.6);
while h > 0.0 {
let block_pos = BlockPos::floored(pos_x, pos_y, pos_z);
let (block, state) =
world.get_block_and_block_state(&block_pos).await.unwrap();
let (block, state) = world.get_block_and_block_state(&block_pos).await;
// if !world.is_in_build_limit(&block_pos) {
// // Pass by reference
@ -72,13 +71,13 @@ impl Explosion {
let blocks = self.get_blocks_to_destroy(world).await;
// TODO: Entity damage, fire
for pos in blocks {
let block_state = world.get_block_state(&pos).await.unwrap();
let block_state = world.get_block_state(&pos).await;
if block_state.is_air() {
continue;
}
let block = world.get_block(&pos).await.unwrap();
let block = world.get_block(&pos).await;
let pumpkin_block = server.block_registry.get_pumpkin_block(&block);
world.set_block_state(&pos, 0, BlockFlags::NOTIFY_ALL).await;

View File

@ -213,7 +213,7 @@ impl World {
// it prevents deadlocks and also removes the need to wait for a lock when adding a new synced block
drop(queue);
for event in events {
let block = self.get_block(&event.pos).await.unwrap(); // TODO
let block = self.get_block(&event.pos).await; // TODO
if !self
.block_registry
.on_synced_block_event(&block, self, &event.pos, event.r#type, event.data)
@ -463,7 +463,7 @@ impl World {
let fluids_to_tick = self.level.get_and_tick_fluid_ticks().await;
for scheduled_tick in blocks_to_tick {
let block = self.get_block(&scheduled_tick.block_pos).await.unwrap();
let block = self.get_block(&scheduled_tick.block_pos).await;
if scheduled_tick.target_block_id != block.id {
continue;
}
@ -506,14 +506,12 @@ impl World {
{
let pos = BlockPos(Vector3::new(position.x, y, position.z));
let block = self.get_block_state(&pos).await;
if let Ok(block) = block {
if block.is_air() {
continue;
}
if block.is_air() {
continue;
}
return y;
}
319
i32::from(generation_settings.shape.height)
}
#[expect(clippy::too_many_lines)]
@ -1378,7 +1376,7 @@ impl World {
.await;
}
let block_state = self.get_block_state(position).await.unwrap();
let block_state = self.get_block_state(position).await;
let new_block = Block::from_state_id(block_state_id).unwrap();
let new_fluid = self.get_fluid(position).await.unwrap_or(Fluid::EMPTY);
@ -1516,8 +1514,7 @@ impl World {
cause: Option<Arc<Player>>,
flags: BlockFlags,
) {
let (broken_block, broken_block_state) =
self.get_block_and_block_state(position).await.unwrap();
let (broken_block, broken_block_state) = self.get_block_and_block_state(position).await;
let event = BlockBreakEvent::new(cause.clone(), broken_block.clone(), *position, 0, false);
let event = PLUGIN_MANAGER
@ -1583,10 +1580,7 @@ impl World {
}
}
pub async fn get_block_state_id(
&self,
position: &BlockPos,
) -> Result<BlockStateId, GetBlockError> {
pub async fn get_block_state_id(&self, position: &BlockPos) -> BlockStateId {
let chunk = self.get_chunk(position).await;
let (_, relative) = position.chunk_and_chunk_relative_position();
@ -1596,49 +1590,43 @@ impl World {
relative.y,
relative.z as usize,
) else {
return Err(GetBlockError::BlockOutOfWorldBounds);
return Block::AIR.default_state_id;
};
Ok(id)
id
}
/// Gets a `Block` from the block registry. Returns `None` if the block was not found.
pub async fn get_block(
&self,
position: &BlockPos,
) -> Result<pumpkin_data::Block, GetBlockError> {
let id = self.get_block_state_id(position).await?;
get_block_by_state_id(id).ok_or(GetBlockError::InvalidBlockId)
/// Gets a `Block` from the block registry. Returns `Block::AIR` if the block was not found.
pub async fn get_block(&self, position: &BlockPos) -> pumpkin_data::Block {
let id = self.get_block_state_id(position).await;
get_block_by_state_id(id).unwrap_or(Block::AIR)
}
pub async fn get_fluid(
&self,
position: &BlockPos,
) -> Result<pumpkin_data::fluid::Fluid, GetBlockError> {
let id = self.get_block_state_id(position).await?;
let id = self.get_block_state_id(position).await;
Fluid::from_state_id(id).ok_or(GetBlockError::InvalidBlockId)
}
/// Gets the `BlockState` from the block registry. Returns `None` if the block state was not found.
pub async fn get_block_state(
&self,
position: &BlockPos,
) -> Result<pumpkin_data::BlockState, GetBlockError> {
let id = self.get_block_state_id(position).await?;
get_state_by_state_id(id).ok_or(GetBlockError::InvalidBlockId)
}
pub fn get_state_by_id(&self, id: u16) -> Result<pumpkin_data::BlockState, GetBlockError> {
get_state_by_state_id(id).ok_or(GetBlockError::InvalidBlockId)
/// Gets the `BlockState` from the block registry. Returns Air if the block state was not found.
pub async fn get_block_state(&self, position: &BlockPos) -> pumpkin_data::BlockState {
let id = self.get_block_state_id(position).await;
get_state_by_state_id(id)
.unwrap_or(get_state_by_state_id(Block::AIR.default_state_id).unwrap())
}
/// Gets the Block + Block state from the Block Registry, Returns None if the Block state has not been found
pub async fn get_block_and_block_state(
&self,
position: &BlockPos,
) -> Result<(pumpkin_data::Block, pumpkin_data::BlockState), GetBlockError> {
let id = self.get_block_state_id(position).await?;
get_block_and_state_by_state_id(id).ok_or(GetBlockError::InvalidBlockId)
) -> (pumpkin_data::Block, pumpkin_data::BlockState) {
let id = self.get_block_state_id(position).await;
get_block_and_state_by_state_id(id).unwrap_or((
Block::AIR,
get_state_by_state_id(Block::AIR.default_state_id).unwrap(),
))
}
/// Updates neighboring blocks of a block
@ -1647,7 +1635,7 @@ impl World {
block_pos: &BlockPos,
except: Option<BlockDirection>,
) {
let source_block = self.get_block(block_pos).await.unwrap();
let source_block = self.get_block(block_pos).await;
for direction in BlockDirection::update_order() {
if except.is_some_and(|d| d == direction) {
continue;
@ -1657,20 +1645,12 @@ impl World {
let neighbor_block = self.get_block(&neighbor_pos).await;
let neighbor_fluid = self.get_fluid(&neighbor_pos).await;
if let Ok(neighbor_block) = neighbor_block {
if let Some(neighbor_pumpkin_block) =
self.block_registry.get_pumpkin_block(&neighbor_block)
{
neighbor_pumpkin_block
.on_neighbor_update(
self,
&neighbor_block,
&neighbor_pos,
&source_block,
false,
)
.await;
}
if let Some(neighbor_pumpkin_block) =
self.block_registry.get_pumpkin_block(&neighbor_block)
{
neighbor_pumpkin_block
.on_neighbor_update(self, &neighbor_block, &neighbor_pos, &source_block, false)
.await;
}
if let Ok(neighbor_fluid) = neighbor_fluid {
@ -1690,7 +1670,7 @@ impl World {
neighbor_block_pos: &BlockPos,
source_block: &Block,
) {
let neighbor_block = self.get_block(neighbor_block_pos).await.unwrap();
let neighbor_block = self.get_block(neighbor_block_pos).await;
if let Some(neighbor_pumpkin_block) = self.block_registry.get_pumpkin_block(&neighbor_block)
{
@ -1712,13 +1692,7 @@ impl World {
direction: BlockDirection,
flags: BlockFlags,
) {
let (block, block_state) = match self.get_block_and_block_state(block_pos).await {
Ok(block) => block,
Err(_error) => {
// Neighbor is outside the world. Don't try to update it
return;
}
};
let (block, block_state) = self.get_block_and_block_state(block_pos).await;
if flags.contains(BlockFlags::SKIP_REDSTONE_WIRE_STATE_REPLACEMENT)
&& block.id == Block::REDSTONE_WIRE.id
@ -1727,7 +1701,7 @@ impl World {
}
let neighbor_pos = block_pos.offset(direction.to_offset());
let neighbor_state_id = self.get_block_state_id(&neighbor_pos).await.unwrap();
let neighbor_state_id = self.get_block_state_id(&neighbor_pos).await;
let new_state_id = self
.block_registry
@ -1902,7 +1876,7 @@ impl pumpkin_world::world::SimpleWorld for World {
Self::set_block_state(&self, position, block_state_id, flags).await
}
async fn get_block(&self, position: &BlockPos) -> Result<pumpkin_data::Block, GetBlockError> {
async fn get_block(&self, position: &BlockPos) -> pumpkin_data::Block {
Self::get_block(self, position).await
}

View File

@ -121,7 +121,7 @@ impl NetherPortal {
let limit_y = pos.0.y - Self::MAX_HEIGHT as i32;
let mut pos = *pos;
while pos.0.y > limit_y {
let (block, state) = world.get_block_and_block_state(&pos.down()).await.unwrap();
let (block, state) = world.get_block_and_block_state(&pos.down()).await;
if !Self::valid_state_inside_portal(&block, &state) {
break;
}
@ -143,17 +143,14 @@ impl NetherPortal {
let mut lower_corner;
for i in 0..=Self::MAX_WIDTH {
lower_corner = original_lower_corner.offset_dir(negative_dir.to_offset(), i as i32);
let (block, block_state) = world
.get_block_and_block_state(&lower_corner)
.await
.unwrap();
let (block, block_state) = world.get_block_and_block_state(&lower_corner).await;
if !Self::valid_state_inside_portal(&block, &block_state) {
if Self::FRAME_BLOCK != block {
break;
}
return i;
}
let block = world.get_block(&lower_corner.down()).await.unwrap();
let block = world.get_block(&lower_corner.down()).await;
if Self::FRAME_BLOCK != block {
break;
}
@ -196,14 +193,14 @@ impl NetherPortal {
let mut pos = lower_corner
.offset_dir(BlockDirection::Up.to_offset(), i)
.offset_dir(negative_dir.to_offset(), -1);
if world.get_block(&pos).await.unwrap() != Self::FRAME_BLOCK {
if world.get_block(&pos).await != Self::FRAME_BLOCK {
return i as u32;
}
pos = lower_corner
.offset_dir(BlockDirection::Up.to_offset(), i)
.offset_dir(negative_dir.to_offset(), width as i32);
if world.get_block(&pos).await.unwrap() != Self::FRAME_BLOCK {
if world.get_block(&pos).await != Self::FRAME_BLOCK {
return i as u32;
}
@ -211,7 +208,7 @@ impl NetherPortal {
pos = lower_corner
.offset_dir(BlockDirection::Up.to_offset(), i)
.offset_dir(negative_dir.to_offset(), j as i32);
let (block, block_state) = world.get_block_and_block_state(&pos).await.unwrap();
let (block, block_state) = world.get_block_and_block_state(&pos).await;
if !Self::valid_state_inside_portal(&block, &block_state) {
return i as u32;
}
@ -235,7 +232,7 @@ impl NetherPortal {
pos = lower_corner
.offset_dir(BlockDirection::Up.to_offset(), height as i32)
.offset_dir(dir.to_offset(), i as i32);
if Self::FRAME_BLOCK != world.get_block(&pos).await.unwrap() {
if Self::FRAME_BLOCK != world.get_block(&pos).await {
return false;
}
}