From 31f8794c39edfb96bccca47b95246592fc896190 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 25 Jul 2019 23:52:28 +0100 Subject: [PATCH] Started work on inventory manipulation --- client/src/lib.rs | 5 ++ common/src/comp/inventory/item.rs | 23 ++++---- common/src/comp/inventory/mod.rs | 30 +++++++++- common/src/msg/client.rs | 1 + common/src/sys/phys.rs | 2 +- server/src/lib.rs | 8 +++ voxygen/src/hud/bag.rs | 95 +++++++++++++++++++------------ voxygen/src/hud/mod.rs | 2 + voxygen/src/session.rs | 3 + 9 files changed, 119 insertions(+), 50 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index c649a7c812..617e2a93ca 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -164,6 +164,11 @@ impl Client { .send_message(ClientMsg::SetViewDistance(self.view_distance.unwrap())); // Can't fail } + pub fn swap_inventory_slots(&mut self, a: usize, b: usize) { + self.postbox + .send_message(ClientMsg::SwapInventorySlots(a, b)) + } + pub fn view_distance(&self) -> Option { self.view_distance } diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs index faca9b5b57..3cb7578a4a 100644 --- a/common/src/comp/inventory/item.rs +++ b/common/src/comp/inventory/item.rs @@ -37,29 +37,30 @@ pub enum Armor { Necklace, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Rarity { - Common, - Uncommon, - Rare, - Legendary, -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Item { Weapon { + kind: Weapon, damage: i32, strength: i32, - rarity: Rarity, }, Armor { + kind: Armor, defense: i32, health_bonus: i32, - rarity: Rarity, - variant: Armor, }, } +impl Default for Item { + fn default() -> Self { + Item::Weapon { + kind: Weapon::Hammer, + damage: 0, + strength: 0, + } + } +} + impl Component for Item { type Storage = IDVStorage; } diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index e11a2581c1..21602ff418 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -17,6 +17,20 @@ impl Inventory { &self.slots } + pub fn len(&self) -> usize { + self.slots.len() + } + + pub fn insert(&mut self, item: Item) -> Option { + match self.slots.iter_mut().find(|slot| slot.is_none()) { + Some(slot) => { + *slot = Some(item); + None + } + None => Some(item), + } + } + // Get info about an item slot pub fn get(&self, cell: usize) -> Option { self.slots.get(cell).cloned().flatten() @@ -28,6 +42,12 @@ impl Inventory { self.slots.get_mut(cell).and_then(|cell| cell.replace(item)) } + pub fn swap_slots(&mut self, a: usize, b: usize) { + if a.max(b) < self.slots.len() { + self.slots.swap(a, b); + } + } + // Remove an item from the slot pub fn remove(&mut self, cell: usize) -> Option { self.slots.get_mut(cell).and_then(|item| item.take()) @@ -36,9 +56,15 @@ impl Inventory { impl Default for Inventory { fn default() -> Inventory { - Inventory { + let mut this = Inventory { slots: vec![None; 8], - } + }; + + this.insert(Item::default()); + this.insert(Item::default()); + this.insert(Item::default()); + + this } } diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 6f3919159b..5322609e9a 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -28,6 +28,7 @@ pub enum ClientMsg { vel: comp::Vel, ori: comp::Ori, }, + SwapInventorySlots(usize, usize), TerrainChunkRequest { key: Vec2, }, diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 7149fdcaaa..b24ff6156d 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -197,7 +197,7 @@ impl<'a> System<'a> for Sys { // ...and the vertical resolution direction is sufficiently great... && -dir.z > 0.1 // ...and we're falling/standing OR there is a block *directly* beneath our current origin (note: not hitbox)... - && (vel.0.z <= 0.0 && terrain + && (vel.0.z > 0.0 || terrain .get((pos.0 - Vec3::unit_z()).map(|e| e.floor() as i32)) .map(|vox| !vox.is_empty()) .unwrap_or(false)) diff --git a/server/src/lib.rs b/server/src/lib.rs index 09f43f2295..a2e93fcecb 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -490,6 +490,14 @@ impl Server { } _ => {} }, + ClientMsg::SwapInventorySlots(a, b) => { + state + .ecs() + .write_storage::() + .get_mut(entity) + .map(|inv| inv.swap_slots(a, b)); + state.write_component(entity, comp::InventoryUpdate); + } ClientMsg::Character { name, body } => match client.client_state { // Become Registered first. ClientState::Connected => { diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index 9549bab947..0ef57614a7 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -1,4 +1,4 @@ -use super::{img_ids::Imgs, Fonts, TEXT_COLOR}; +use super::{img_ids::Imgs, Event as HudEvent, Fonts, TEXT_COLOR}; use client::Client; use conrod_core::{ color, @@ -17,10 +17,10 @@ widget_ids! { inv_grid_1, inv_grid_2, inv_scrollbar, - inv_slot_0, + inv_slots_0, map_title, - inv_slot[], - item1, + inv_slots[], + items[], } } @@ -51,6 +51,7 @@ pub struct State { const BAG_SCALE: f64 = 4.0; pub enum Event { + HudEvent(HudEvent), Close, } @@ -72,12 +73,13 @@ impl<'a> Widget for Bag<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; - let inventory_slots = self - .client - .inventories() - .get(self.client.entity()) - .map(|inv| inv.slots().len()) - .unwrap_or(0); + let mut event = None; + + let invs = self.client.inventories(); + let inventory = match invs.get(self.client.entity()) { + Some(inv) => inv, + None => return None, + }; // Bag parts Image::new(self.imgs.bag_bot) @@ -85,7 +87,7 @@ impl<'a> Widget for Bag<'a> { .bottom_right_with_margins_on(ui.window, 60.0, 5.0) .set(state.ids.bag_bot, ui); Image::new(self.imgs.bag_mid) - .w_h(61.0 * BAG_SCALE, ((inventory_slots + 4) / 5) as f64 * 44.0) + .w_h(61.0 * BAG_SCALE, ((inventory.len() + 4) / 5) as f64 * 44.0) .up_from(state.ids.bag_bot, 0.0) .set(state.ids.bag_mid, ui); Image::new(self.imgs.bag_top) @@ -95,7 +97,7 @@ impl<'a> Widget for Bag<'a> { // Alignment for Grid Rectangle::fill_with( - [54.0 * BAG_SCALE, ((inventory_slots + 4) / 5) as f64 * 44.0], + [54.0 * BAG_SCALE, ((inventory.len() + 4) / 5) as f64 * 44.0], color::TRANSPARENT, ) .top_left_with_margins_on(state.ids.bag_top, 9.0 * BAG_SCALE, 3.0 * BAG_SCALE) @@ -120,18 +122,31 @@ impl<'a> Widget for Bag<'a> { .set(state.ids.inv_scrollbar, ui);*/ // Create available inventory slot widgets - if state.ids.inv_slot.len() < inventory_slots { + + if state.ids.inv_slots.len() < inventory.len() { state.update(|s| { s.ids - .inv_slot - .resize(inventory_slots, &mut ui.widget_id_generator()); + .inv_slots + .resize(inventory.len(), &mut ui.widget_id_generator()); }); } - // "Allowed" max. inventory space should be handled serverside and thus isn't limited in the UI - for i in 0..inventory_slots { + + if state.ids.items.len() < inventory.len() { + state.update(|s| { + s.ids + .items + .resize(inventory.len(), &mut ui.widget_id_generator()); + }); + } + + // Display inventory contents + + for (i, item) in inventory.slots().iter().enumerate() { let x = i % 5; let y = i / 5; - Button::image(self.imgs.inv_slot) + + // Slot + if Button::image(self.imgs.inv_slot) .top_left_with_margins_on( state.ids.inv_alignment, 4.0 + y as f64 * (40.0 + 4.0), @@ -139,22 +154,30 @@ impl<'a> Widget for Bag<'a> { ) // conrod uses a (y,x) format for placing... .parent(state.ids.bag_mid) // Avoids the background overlapping available slots .w_h(40.0, 40.0) - .set(state.ids.inv_slot[i], ui); + .set(state.ids.inv_slots[i], ui) + .was_clicked() + { + event = Some(Event::HudEvent(HudEvent::SwapInventorySlots(0, i))); + } + + // Item + if item.is_some() { + Button::image(self.imgs.potion_red) // TODO: Insert variable image depending on the item displayed in that slot + .w_h(4.0 * 4.4, 7.0 * 4.4) // TODO: Fix height and scale width correctly to that to avoid a stretched item image + .middle_of(state.ids.inv_slots[i]) // TODO: Items need to be assigned to a certain slot and then placed like in this example + .label("5x") // TODO: Quantity goes here... + .label_font_id(self.fonts.opensans) + .label_font_size(12) + .label_x(Relative::Scalar(10.0)) + .label_y(Relative::Scalar(-10.0)) + .label_color(TEXT_COLOR) + .parent(state.ids.inv_slots[i]) + .set(state.ids.items[i], ui); + } } - // Test Item - if inventory_slots > 0 { - Button::image(self.imgs.potion_red) // TODO: Insert variable image depending on the item displayed in that slot - .w_h(4.0 * 4.4, 7.0 * 4.4) // TODO: Fix height and scale width correctly to that to avoid a stretched item image - .middle_of(state.ids.inv_slot[0]) // TODO: Items need to be assigned to a certain slot and then placed like in this example - .label("5x") // TODO: Quantity goes here... - .label_font_id(self.fonts.opensans) - .label_font_size(12) - .label_x(Relative::Scalar(10.0)) - .label_y(Relative::Scalar(-10.0)) - .label_color(TEXT_COLOR) - .set(state.ids.item1, ui); // TODO: Add widget_id generator for displayed items - } - // X-button + + // Close button + if Button::image(self.imgs.close_button) .w_h(28.0, 28.0) .hover_image(self.imgs.close_button_hover) @@ -163,9 +186,9 @@ impl<'a> Widget for Bag<'a> { .set(state.ids.bag_close, ui) .was_clicked() { - Some(Event::Close) - } else { - None + event = Some(Event::Close); } + + event } } diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index c3d3b50a25..f7c1afb456 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -141,6 +141,7 @@ pub enum Event { CrosshairType(CrosshairType), UiScale(ScaleChange), CharacterSelection, + SwapInventorySlots(usize, usize), Logout, Quit, } @@ -589,6 +590,7 @@ impl Hud { // Bag contents if self.show.bag { match Bag::new(client, &self.imgs, &self.fonts).set(self.ids.bag, ui_widgets) { + Some(bag::Event::HudEvent(event)) => events.push(event), Some(bag::Event::Close) => { self.show.bag(false); self.force_ungrab = true; diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 7279c89470..a2e2833b50 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -318,6 +318,9 @@ impl PlayState for SessionState { global_state.settings.graphics.max_fps = fps; global_state.settings.save_to_file_warn(); } + HudEvent::SwapInventorySlots(a, b) => { + self.client.borrow_mut().swap_inventory_slots(a, b) + } } }