Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/blocks/crates/data/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub struct PlacementContext<'a> {
pub level: &'a World,
pub dimension: Dimension,
pub player_rotation: &'a Rotation,
pub default_placement_state: BlockStateId,
}

/// Result of the get_placement_state function
Expand Down
25 changes: 23 additions & 2 deletions src/blocks/src/building/slab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,28 @@ impl BlockBehavior for SlabBlock {
PlacedBlocks::default()
}

fn can_be_replaced(&self, _context: PlacementContext) -> bool {
true
fn can_be_replaced(&self, context: PlacementContext) -> bool {
if matches!(self.ty, SlabType::Double) {
return false;
}

if !matches!(context.face, BlockFace::Top | BlockFace::Bottom) {
return false;
}

let expected_face = match self.ty {
SlabType::Top => BlockFace::Bottom,
SlabType::Bottom => BlockFace::Top,
SlabType::Double => unreachable!(),
};

if context.face != expected_face {
return false;
}

context
.default_placement_state
.try_cast::<SlabBlock>()
.is_some_and(|slab| slab.block_type == self.block_type)
}
}
4 changes: 2 additions & 2 deletions src/blocks/src/decorative/fence_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl BlockBehavior for FenceAndPaneBlock {
&mut self.south,
&mut self.west,
]) {
let pos = context.block_pos + IVec3::new(*dx, 0, *dz).into();
let pos = context.block_pos + IVec3::new(*dx, 0, *dz);
let block = context
.level
.get_block(pos, context.dimension)
Expand Down Expand Up @@ -61,7 +61,7 @@ impl BlockBehavior for FenceAndPaneBlock {
&mut self.south,
&mut self.west,
]) {
let pos = pos + IVec3::new(*dx, 0, *dz).into();
let pos = pos + IVec3::new(*dx, 0, *dz);
let block = world
.get_block(pos, Dimension::Overworld)
.unwrap_or_default();
Expand Down
2 changes: 1 addition & 1 deletion src/core/src/block_face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use temper_codec::decode::errors::NetDecodeError;
use temper_codec::decode::{NetDecode, NetDecodeOpts};
use temper_codec::net_types::var_int::VarInt;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum BlockFace {
Top,
Bottom,
Expand Down
10 changes: 10 additions & 0 deletions src/core/src/pos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ impl Add<(i32, i32, i32)> for BlockPos {
}
}

impl Add<IVec3> for BlockPos {
type Output = BlockPos;

fn add(self, rhs: IVec3) -> Self::Output {
Self {
pos: self.pos + rhs,
}
}
}

#[derive(Clone, Copy, DeepSizeOf, Serialize, Deserialize, TypeHash)]
pub struct ChunkHeight {
pub min_y: i16,
Expand Down
65 changes: 40 additions & 25 deletions src/game_systems/src/packets/src/place_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,12 @@ pub fn handle(
continue 'ev_loop;
}

let offset_pos = block_pos
let mut offset_pos = block_pos
+ IVec3::new(
(event.cursor_x * 2.0 - 1.0) as i32,
(event.cursor_y * 2.0 - 1.0) as i32,
(event.cursor_z * 2.0 - 1.0) as i32,
)
.into();
);

let Ok(curr_state) = state.0.world.get_block(offset_pos, Dimension::Overworld)
else {
Expand Down Expand Up @@ -159,8 +158,15 @@ pub fn handle(
continue 'ev_loop;
}

let placement_context = temper_blocks::PlacementContext {
face: event.face,
let mut block_state = ITEM_TO_BLOCK_MAPPING
.get()
.unwrap()
.get(&(item_id.as_u32() as i32))
.copied()
.unwrap();

let mut placement_context = temper_blocks::PlacementContext {
face: event.face.clone(),
cursor: DVec3::new(
f64::from(event.cursor_x),
f64::from(event.cursor_y),
Expand All @@ -171,36 +177,45 @@ pub fn handle(
level: &state.0.world,
dimension: Dimension::Overworld,
player_rotation: rot,
default_placement_state: block_state,
};

// Try to replace the block from the offset calculated
if !curr_state.can_be_replaced(placement_context.clone()) {
if let Err(err) = conn.send_packet_ref(&ack_packet) {
error!("Failed to send block change ack packet: {:?}", err);
// If the block cannot be replaced, try to replace the block adjacent to the face clicked
offset_pos = block_pos + event.face.get_normal();

let Ok(curr_state) =
state.0.world.get_block(offset_pos, Dimension::Overworld)
else {
error!("Can't get block at {}", offset_pos);
continue 'ev_loop;
}
};

if !curr_state.can_be_replaced(placement_context.clone()) {
if let Err(err) = conn.send_packet_ref(&ack_packet) {
error!("Failed to send block change ack packet: {:?}", err);
continue 'ev_loop;
}

if let Err(err) = conn.send_packet(BlockUpdate {
location: NetworkPosition {
x: offset_pos.pos.x,
y: offset_pos.pos.y as i16,
z: offset_pos.pos.z,
},
block_state_id: curr_state.to_varint(),
}) {
error!("Failed to send block update packet to player: {err}");
continue 'ev_loop;
}

if let Err(err) = conn.send_packet(BlockUpdate {
location: NetworkPosition {
x: offset_pos.pos.x,
y: offset_pos.pos.y as i16,
z: offset_pos.pos.z,
},
block_state_id: curr_state.to_varint(),
}) {
error!("Failed to send block update packet to player: {err}");
continue 'ev_loop;
}

continue 'ev_loop;
placement_context.block_pos = offset_pos;
}

let mut block_state = ITEM_TO_BLOCK_MAPPING
.get()
.unwrap()
.get(&(item_id.as_u32() as i32))
.copied()
.unwrap();

let mut placed_blocks = block_state.get_placement_state(placement_context);

if placed_blocks.place_original {
Expand Down
Loading