diff --git a/assets/blocks/planks.png b/assets/blocks/planks.png new file mode 100644 index 0000000..c06e269 Binary files /dev/null and b/assets/blocks/planks.png differ diff --git a/kubi-shared/src/block.rs b/kubi-shared/src/block.rs index 76a126b..7244b2c 100644 --- a/kubi-shared/src/block.rs +++ b/kubi-shared/src/block.rs @@ -18,6 +18,7 @@ pub enum BlockTexture { Snow, GrassSideSnow, Cobblestone, + Planks, } #[derive(Encode, Decode, Clone, Copy, Debug, PartialEq, Eq, EnumIter)] @@ -30,6 +31,7 @@ pub enum Block { Sand, Cobblestone, TallGrass, + Planks, } impl Block { @@ -81,7 +83,13 @@ impl Block { render: RenderType::CrossShape(CrossTexture::all(BlockTexture::TallGrass)), collision: CollisionType::None, raycast_collision: true, - } + }, + Self::Planks => BlockDescriptor { + name: "planks", + render: RenderType::SolidBlock(CubeTexture::all(BlockTexture::Planks)), + collision: CollisionType::Solid, + raycast_collision: true, + }, } } } diff --git a/kubi/src/block_placement.rs b/kubi/src/block_placement.rs index 0a08390..36605d2 100644 --- a/kubi/src/block_placement.rs +++ b/kubi/src/block_placement.rs @@ -1,14 +1,47 @@ -use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut}; +use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut, Component, Workload, IntoWorkload}; +use glium::glutin::event::VirtualKeyCode; use kubi_shared::block::Block; use crate::{ player::MainPlayer, - world::{raycast::LookingAtBlock, queue::{BlockUpdateQueue, BlockUpdateEvent}}, - input::{Inputs, PrevInputs}, + world::{raycast::{LookingAtBlock, RAYCAST_STEP}, queue::{BlockUpdateQueue, BlockUpdateEvent}}, + input::{Inputs, PrevInputs, RawKbmInputState}, events::{EventComponent, player_actions::PlayerActionEvent}, }; -pub fn block_placement_system( +#[derive(Component)] +pub struct PlayerHolding(pub Block); +impl Default for PlayerHolding { + fn default() -> Self { + Self(Block::Cobblestone) + } +} + +const BLOCK_KEY_MAP: &[(VirtualKeyCode, Block)] = &[ + (VirtualKeyCode::Key1, Block::Cobblestone), + (VirtualKeyCode::Key2, Block::Planks), + (VirtualKeyCode::Key3, Block::Dirt), + (VirtualKeyCode::Key4, Block::Grass), + (VirtualKeyCode::Key5, Block::Sand), + (VirtualKeyCode::Key6, Block::Stone), +]; + +fn pick_block_with_number_keys( main_player: View, + mut holding: ViewMut, + input: UniqueView, +) { + let Some((_, mut holding)) = (&main_player, &mut holding).iter().next() else { return }; + for &(key, block) in BLOCK_KEY_MAP { + if input.keyboard_state.contains(&key) { + holding.0 = block; + return + } + } +} + +fn block_placement_system( + main_player: View, + holding: View, raycast: View, input: UniqueView, prev_input: UniqueView, @@ -20,12 +53,14 @@ pub fn block_placement_system( let action_place = input.action_b && !prev_input.0.action_b; let action_break = input.action_a && !prev_input.0.action_a; if action_place ^ action_break { - //get raycast info - let Some(ray) = (&main_player, &raycast).iter().next().unwrap().1/**/.0 else { return }; + //get components + let Some((_, ray, block)) = (&main_player, &raycast, &holding).iter().next() else { return }; + let Some(ray) = ray.0 else { return }; //get coord and block type let (place_position, place_block) = if action_place { - let position = (ray.position - ray.direction * 0.251).floor().as_ivec3(); - (position, Block::Cobblestone) + if block.0 == Block::Air { return } + let position = (ray.position - ray.direction * (RAYCAST_STEP + 0.001)).floor().as_ivec3(); + (position, block.0) } else { (ray.block_position, Block::Air) }; @@ -44,3 +79,10 @@ pub fn block_placement_system( ); } } + +pub fn update_block_placement() -> Workload { + ( + pick_block_with_number_keys, + block_placement_system + ).into_workload() +} diff --git a/kubi/src/control_flow.rs b/kubi/src/control_flow.rs index 253dbdb..9dad6e1 100644 --- a/kubi/src/control_flow.rs +++ b/kubi/src/control_flow.rs @@ -1,12 +1,12 @@ use shipyard::{UniqueView, UniqueViewMut, Unique, AllStoragesView}; use glium::glutin::{event::VirtualKeyCode, event_loop::ControlFlow}; -use crate::input::RawInputState; +use crate::input::RawKbmInputState; #[derive(Unique)] pub struct SetControlFlow(pub Option); pub fn exit_on_esc( - raw_inputs: UniqueView, + raw_inputs: UniqueView, mut control_flow: UniqueViewMut ) { if raw_inputs.keyboard_state.contains(&VirtualKeyCode::Escape) { diff --git a/kubi/src/input.rs b/kubi/src/input.rs index 6b92835..fe9fd57 100644 --- a/kubi/src/input.rs +++ b/kubi/src/input.rs @@ -18,7 +18,7 @@ pub struct Inputs { pub struct PrevInputs(pub Inputs); #[derive(Unique, Clone, Default, Debug)] -pub struct RawInputState { +pub struct RawKbmInputState { pub keyboard_state: HashSet>, pub button_state: [bool; 32], pub mouse_delta: DVec2 @@ -35,7 +35,7 @@ pub struct ActiveGamepad(Option); fn process_events( device_events: View, - mut input_state: UniqueViewMut, + mut input_state: UniqueViewMut, ) { input_state.mouse_delta = DVec2::ZERO; for event in device_events.iter() { @@ -79,7 +79,7 @@ fn input_start( } fn update_input_state ( - raw_inputs: UniqueView, + raw_inputs: UniqueView, mut inputs: UniqueViewMut, ) { inputs.movement += Vec2::new( @@ -123,7 +123,7 @@ pub fn init_input ( storages.add_unique(ActiveGamepad::default()); storages.add_unique(Inputs::default()); storages.add_unique(PrevInputs::default()); - storages.add_unique(RawInputState::default()); + storages.add_unique(RawKbmInputState::default()); } pub fn process_inputs() -> Workload { diff --git a/kubi/src/main.rs b/kubi/src/main.rs index c02f929..472d3c0 100644 --- a/kubi/src/main.rs +++ b/kubi/src/main.rs @@ -72,7 +72,7 @@ use rendering::{ world::draw_world, world::draw_current_chunk_border, }; -use block_placement::block_placement_system; +use block_placement::update_block_placement; use delta_time::{DeltaTime, init_delta_time}; use cursor_lock::{insert_lock_state, update_cursor_lock_state, lock_cursor_now}; use control_flow::{exit_on_esc, insert_control_flow_unique, SetControlFlow}; @@ -124,7 +124,7 @@ fn update() -> Workload { update_controllers, generate_move_events, update_raycasts, - block_placement_system, + update_block_placement, apply_queued_blocks, ).into_workload().run_if(is_ingame), compute_cameras, diff --git a/kubi/src/player.rs b/kubi/src/player.rs index a6afaed..cc1e705 100644 --- a/kubi/src/player.rs +++ b/kubi/src/player.rs @@ -3,7 +3,8 @@ use crate::{ transform::Transform, camera::Camera, fly_controller::FlyController, - world::raycast::LookingAtBlock, + world::raycast::LookingAtBlock, + block_placement::PlayerHolding, }; #[derive(Component)] @@ -23,5 +24,6 @@ pub fn spawn_player ( Camera::default(), FlyController, LookingAtBlock::default(), + PlayerHolding::default(), )); } diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 1fc81b5..c1ec11b 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -30,6 +30,7 @@ impl AssetPaths for BlockTexture { Self::Snow => "snow.png", Self::GrassSideSnow => "grass_side_snow.png", Self::Cobblestone => "cobblestone.png", + Self::Planks => "planks.png", } } } diff --git a/kubi/src/world/raycast.rs b/kubi/src/world/raycast.rs index c545595..c0d1c3c 100644 --- a/kubi/src/world/raycast.rs +++ b/kubi/src/world/raycast.rs @@ -4,7 +4,7 @@ use kubi_shared::block::Block; use crate::transform::Transform; use super::ChunkStorage; -const RAYCAST_STEP: f32 = 0.25; +pub const RAYCAST_STEP: f32 = 0.25; #[derive(Clone, Copy, Debug)] pub struct RaycastReport {