From 39fc1d6b7162ac3979bae5765df4af4f553fa4a9 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 29 Jul 2019 17:19:08 +0100 Subject: [PATCH] Added entity pickup, changed item model --- assets/voxygen/voxel/object/pouch.vox | 3 ++ client/src/lib.rs | 10 ++++-- common/src/comp/body/object.rs | 1 + common/src/comp/phys.rs | 6 ++-- common/src/msg/client.rs | 1 + common/src/sys/phys.rs | 7 +++- server/src/lib.rs | 49 ++++++++++++++++++++++++--- voxygen/src/scene/figure.rs | 10 ++++-- voxygen/src/session.rs | 30 ++++++++++++++++ voxygen/src/settings.rs | 2 ++ voxygen/src/window.rs | 2 ++ 11 files changed, 108 insertions(+), 13 deletions(-) create mode 100644 assets/voxygen/voxel/object/pouch.vox diff --git a/assets/voxygen/voxel/object/pouch.vox b/assets/voxygen/voxel/object/pouch.vox new file mode 100644 index 0000000000..4f863db0a9 --- /dev/null +++ b/assets/voxygen/voxel/object/pouch.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41c5c4dacb7050121ce597d73957976e7476630e0078c2d9536fe179855b8edf +size 58277 diff --git a/client/src/lib.rs b/client/src/lib.rs index 5da4d11abb..a296cb567b 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -4,13 +4,13 @@ pub mod error; // Reexports pub use crate::error::Error; -pub use specs::{join::Join, Entity as EcsEntity, ReadStorage}; +pub use specs::{join::Join, saveload::Marker, Entity as EcsEntity, ReadStorage}; use common::{ comp, msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg}, net::PostBox, - state::State, + state::{State, Uid}, terrain::{block::Block, chonk::ChonkMetrics, TerrainChunk, TerrainChunkSize}, vol::VolSize, ChatType, @@ -173,6 +173,12 @@ impl Client { self.postbox.send_message(ClientMsg::DropInventorySlot(x)) } + pub fn pick_up(&mut self, entity: EcsEntity) { + if let Some(uid) = self.state.ecs().read_storage::().get(entity).copied() { + self.postbox.send_message(ClientMsg::PickUp(uid.id())); + } + } + pub fn view_distance(&self) -> Option { self.view_distance } diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index f45cea9d2e..0bd17f3fe7 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -48,6 +48,7 @@ pub enum Body { CarpetHumanSquare, CarpetHumanSquare2, CarpetHumanSquircle, + Pouch, } impl Body { diff --git a/common/src/comp/phys.rs b/common/src/comp/phys.rs index 46144c8977..977f85f21d 100644 --- a/common/src/comp/phys.rs +++ b/common/src/comp/phys.rs @@ -3,7 +3,7 @@ use specs_idvs::IDVStorage; use vek::*; // Position -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct Pos(pub Vec3); impl Component for Pos { @@ -11,7 +11,7 @@ impl Component for Pos { } // Velocity -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct Vel(pub Vec3); impl Component for Vel { @@ -19,7 +19,7 @@ impl Component for Vel { } // Orientation -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct Ori(pub Vec3); impl Component for Ori { diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index b2acf4a0b8..cc325415d8 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -30,6 +30,7 @@ pub enum ClientMsg { }, SwapInventorySlots(usize, usize), DropInventorySlot(usize), + PickUp(u64), TerrainChunkRequest { key: Vec2, }, diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 2845d778f0..1eaf57693a 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -63,7 +63,12 @@ impl<'a> System<'a> for Sys { { // Integrate forces // Friction is assumed to be a constant dependent on location - let friction = 50.0 * if a.on_ground { FRIC_GROUND } else { FRIC_AIR }; + let friction = 50.0 + * if on_grounds.get(entity).is_some() { + FRIC_GROUND + } else { + FRIC_AIR + }; vel.0 = integrate_forces(dt.0, vel.0, GRAVITY, friction); // Basic collision with terrain diff --git a/server/src/lib.rs b/server/src/lib.rs index 011740e210..54ff766ee2 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -506,12 +506,49 @@ impl Server { state.write_component(entity, comp::InventoryUpdate); - if let (Some(pos), Some(item)) = - (state.ecs().read_storage::().get(entity), item) + if let (Some(item), Some(pos)) = + (item, state.ecs().read_storage::().get(entity)) { - dropped_items.push((*pos, item)); + dropped_items.push(( + *pos, + state + .ecs() + .read_storage::() + .get(entity) + .copied() + .unwrap_or(comp::Ori(Vec3::unit_y())), + item, + )); } } + ClientMsg::PickUp(uid) => { + let item_entity = state.ecs_mut().entity_from_uid(uid); + + let ecs = state.ecs_mut(); + + let item_entity = if let (Some((item, item_entity)), Some(inv)) = ( + item_entity.and_then(|item_entity| { + ecs.write_storage::() + .get_mut(item_entity) + .map(|item| (*item, item_entity)) + }), + ecs.write_storage::().get_mut(entity), + ) { + if inv.insert(item).is_none() { + Some(item_entity) + } else { + None + } + } else { + None + }; + + if let Some(item_entity) = item_entity { + let _ = ecs.delete_entity_synced(item_entity); + } + + state.write_component(entity, comp::InventoryUpdate); + } ClientMsg::Character { name, body } => match client.client_state { // Become Registered first. ClientState::Connected => { @@ -688,9 +725,11 @@ impl Server { self.state.set_block(pos, block); } - for (pos, item) in dropped_items { - self.create_object(pos, comp::object::Body::Crate) + for (pos, ori, item) in dropped_items { + self.create_object(Default::default(), comp::object::Body::Pouch) + .with(comp::Pos(pos.0 + Vec3::unit_z() * 1.0)) .with(item) + .with(comp::Vel(ori.0.normalized() * 2.0 + Vec3::unit_z() * 2.0)) .build(); } diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 490ed27f08..8a8d800b83 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -583,6 +583,7 @@ impl FigureModelCache { "object/carpet_human_squircle.vox", Vec3::new(-21.0, -21.0, -0.5), ), + object::Body::Pouch => ("object/pouch.vox", Vec3::new(-5.5, -4.5, 0.0)), }; Self::load_mesh(name, offset) } @@ -970,8 +971,13 @@ impl FigureState { dt: f32, ) { // Update interpolation values - self.pos = Lerp::lerp(self.pos, pos, 15.0 * dt); - self.ori = Slerp::slerp(self.ori, ori, 7.5 * dt); + if self.pos.distance_squared(pos) < 64.0 * 64.0 { + self.pos = Lerp::lerp(self.pos, pos, 15.0 * dt); + self.ori = Slerp::slerp(self.ori, ori, 7.5 * dt); + } else { + self.pos = pos; + self.ori = ori; + } let mat = Mat4::::identity() * Mat4::translation_3d(self.pos) diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index cd728ff573..647d83675a 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -9,6 +9,7 @@ use crate::{ use client::{self, Client}; use common::{clock::Clock, comp, comp::Pos, msg::ClientState, terrain::Block, vol::ReadVol}; use log::error; +use specs::Join; use std::{cell::RefCell, rc::Rc, time::Duration}; use vek::*; @@ -212,6 +213,35 @@ impl PlayState for SessionState { Event::InputUpdate(GameInput::Glide, state) => { self.controller.glide = state; } + Event::InputUpdate(GameInput::Interact, state) => { + let mut client = self.client.borrow_mut(); + + let player_pos = client + .state() + .read_storage::() + .get(client.entity()) + .copied(); + + if let (Some(player_pos), true) = (player_pos, state) { + let entity = ( + &client.state().ecs().entities(), + &client.state().ecs().read_storage::(), + &client.state().ecs().read_storage::(), + ) + .join() + .filter(|(_, pos, _)| { + pos.0.distance_squared(player_pos.0) < 3.0 * 3.0 + }) + .min_by_key(|(_, pos, _)| { + (pos.0.distance_squared(player_pos.0) * 1000.0) as i32 + }) + .map(|(entity, _, _)| entity); + + if let Some(entity) = entity { + client.pick_up(entity); + } + } + } // Pass all other events to the scene event => { diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 8995241ffc..938e77bb82 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -35,6 +35,7 @@ pub struct ControlSettings { pub attack: KeyMouse, pub second_attack: KeyMouse, pub roll: KeyMouse, + pub interact: KeyMouse, } impl Default for ControlSettings { @@ -66,6 +67,7 @@ impl Default for ControlSettings { attack: KeyMouse::Mouse(MouseButton::Left), second_attack: KeyMouse::Mouse(MouseButton::Right), roll: KeyMouse::Mouse(MouseButton::Middle), + interact: KeyMouse::Key(VirtualKeyCode::E), } } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 88dff356f8..a7b5dc2266 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -38,6 +38,7 @@ pub enum GameInput { SecondAttack, Roll, Respawn, + Interact, } /// Represents an incoming event from the window. @@ -143,6 +144,7 @@ impl Window { key_map.insert(settings.controls.attack, GameInput::Attack); key_map.insert(settings.controls.second_attack, GameInput::SecondAttack); key_map.insert(settings.controls.roll, GameInput::Roll); + key_map.insert(settings.controls.interact, GameInput::Interact); let keypress_map = HashMap::new();