diff --git a/client/src/lib.rs b/client/src/lib.rs index 4074046647..9609649ced 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -250,6 +250,10 @@ impl Client { self.postbox.send_message(ClientMsg::BreakBlock(pos)); } + pub fn collect_block(&mut self, pos: Vec3) { + self.postbox.send_message(ClientMsg::CollectBlock(pos)); + } + /// Execute a single client tick, handle input and update the game state by the given duration. #[allow(dead_code)] pub fn tick( diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index c3639562bd..1e98732283 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -19,6 +19,7 @@ pub enum ClientMsg { SetViewDistance(u32), BreakBlock(Vec3), PlaceBlock(Vec3, Block), + CollectBlock(Vec3), Ping, Pong, ChatMsg { diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index d5ae62fbd9..3184b9ebd8 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -128,6 +128,15 @@ impl BlockKind { _ => true, } } + + pub fn is_collectible(&self) -> bool { + match self { + BlockKind::Apple => true, + BlockKind::Mushroom => true, + BlockKind::Velorite => true, + _ => false, + } + } } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/server/src/lib.rs b/server/src/lib.rs index cb48ea2b29..aef49e9491 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1011,13 +1011,7 @@ impl Server { .get(entity) .is_some() { - let block = state.terrain().get(pos).ok().copied(); - - if state.try_set_block(pos, Block::empty()).is_some() { - block - .and_then(|block| comp::Item::try_reclaim_from_block(block)) - .map(|item| state.give_item(entity, item)); - } + state.set_block(pos, Block::empty()); } } ClientMsg::PlaceBlock(pos, block) => { @@ -1030,6 +1024,17 @@ impl Server { state.try_set_block(pos, block); } } + ClientMsg::CollectBlock(pos) => { + let block = state.terrain().get(pos).ok().copied(); + if let Some(block) = block { + if block.is_collectible() { + if state.try_set_block(pos, Block::empty()).is_some() { + comp::Item::try_reclaim_from_block(block) + .map(|item| state.give_item(entity, item)); + } + } + } + } ClientMsg::TerrainChunkRequest { key } => match client.client_state { ClientState::Connected | ClientState::Registered diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 67796b5b67..6e81cf5f4b 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -162,7 +162,25 @@ impl PlayState for SessionState { } Event::InputUpdate(GameInput::Secondary, state) => { + self.controller.secondary = false; // To be changed later on + let mut client = self.client.borrow_mut(); + + let hit_pos = { + let terrain = client.state().terrain(); + let ray = terrain + .ray(cam_pos, cam_pos + cam_dir * 100.0) + .until(|block| block.is_tangeable()) + .cast(); + let dist = ray.0; + if let Ok(Some(_)) = ray.1 { + // Hit something! + Some((cam_pos + cam_dir * dist).map(|e| e.floor() as i32)) + } else { + None + } + }; + if state && client .state() @@ -170,21 +188,21 @@ impl PlayState for SessionState { .get(client.entity()) .is_some() { - let (d, b) = { - let terrain = client.state().terrain(); - let ray = terrain - .ray(cam_pos, cam_pos + cam_dir * 100.0) - .until(|block| block.is_tangeable()) - .cast(); - (ray.0, if let Ok(Some(_)) = ray.1 { true } else { false }) - }; - - if b { - let pos = (cam_pos + cam_dir * d).map(|e| e.floor() as i32); - client.remove_block(pos); + if let Some(hit_pos) = hit_pos { + client.remove_block(hit_pos); } - } else { + } else if client + .state() + .read_storage::() + .get(client.entity()) + .map(|cs| cs.action.is_wield()) + .unwrap_or(false) + { self.controller.secondary = state; + } else { + if let Some(hit_pos) = hit_pos { + client.collect_block(hit_pos); + } } } Event::InputUpdate(GameInput::Roll, state) => {