Less unwraps more fun
This commit is contained in:
parent
d6be9823a5
commit
68c24366c3
@ -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::*;
|
||||
|
||||
35
pumpkin-protocol/src/server/play/set_command_block.rs
Normal file
35
pumpkin-protocol/src/server/play/set_command_block.rs
Normal 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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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))),
|
||||
|
||||
54
pumpkin-world/src/block/entities/command_block.rs
Normal file
54
pumpkin-world/src/block/entities/command_block.rs
Normal 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
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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>,
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
91
pumpkin/src/block/blocks/command.rs
Normal file
91
pumpkin/src/block/blocks/command.rs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user