mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Started work on inventory manipulation
This commit is contained in:
@ -164,6 +164,11 @@ impl Client {
|
|||||||
.send_message(ClientMsg::SetViewDistance(self.view_distance.unwrap())); // Can't fail
|
.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<u32> {
|
pub fn view_distance(&self) -> Option<u32> {
|
||||||
self.view_distance
|
self.view_distance
|
||||||
}
|
}
|
||||||
|
@ -37,29 +37,30 @@ pub enum Armor {
|
|||||||
Necklace,
|
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)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum Item {
|
pub enum Item {
|
||||||
Weapon {
|
Weapon {
|
||||||
|
kind: Weapon,
|
||||||
damage: i32,
|
damage: i32,
|
||||||
strength: i32,
|
strength: i32,
|
||||||
rarity: Rarity,
|
|
||||||
},
|
},
|
||||||
Armor {
|
Armor {
|
||||||
|
kind: Armor,
|
||||||
defense: i32,
|
defense: i32,
|
||||||
health_bonus: 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 {
|
impl Component for Item {
|
||||||
type Storage = IDVStorage<Self>;
|
type Storage = IDVStorage<Self>;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,20 @@ impl Inventory {
|
|||||||
&self.slots
|
&self.slots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.slots.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, item: Item) -> Option<Item> {
|
||||||
|
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
|
// Get info about an item slot
|
||||||
pub fn get(&self, cell: usize) -> Option<Item> {
|
pub fn get(&self, cell: usize) -> Option<Item> {
|
||||||
self.slots.get(cell).cloned().flatten()
|
self.slots.get(cell).cloned().flatten()
|
||||||
@ -28,6 +42,12 @@ impl Inventory {
|
|||||||
self.slots.get_mut(cell).and_then(|cell| cell.replace(item))
|
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
|
// Remove an item from the slot
|
||||||
pub fn remove(&mut self, cell: usize) -> Option<Item> {
|
pub fn remove(&mut self, cell: usize) -> Option<Item> {
|
||||||
self.slots.get_mut(cell).and_then(|item| item.take())
|
self.slots.get_mut(cell).and_then(|item| item.take())
|
||||||
@ -36,9 +56,15 @@ impl Inventory {
|
|||||||
|
|
||||||
impl Default for Inventory {
|
impl Default for Inventory {
|
||||||
fn default() -> Inventory {
|
fn default() -> Inventory {
|
||||||
Inventory {
|
let mut this = Inventory {
|
||||||
slots: vec![None; 8],
|
slots: vec![None; 8],
|
||||||
}
|
};
|
||||||
|
|
||||||
|
this.insert(Item::default());
|
||||||
|
this.insert(Item::default());
|
||||||
|
this.insert(Item::default());
|
||||||
|
|
||||||
|
this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ pub enum ClientMsg {
|
|||||||
vel: comp::Vel,
|
vel: comp::Vel,
|
||||||
ori: comp::Ori,
|
ori: comp::Ori,
|
||||||
},
|
},
|
||||||
|
SwapInventorySlots(usize, usize),
|
||||||
TerrainChunkRequest {
|
TerrainChunkRequest {
|
||||||
key: Vec2<i32>,
|
key: Vec2<i32>,
|
||||||
},
|
},
|
||||||
|
@ -197,7 +197,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
// ...and the vertical resolution direction is sufficiently great...
|
// ...and the vertical resolution direction is sufficiently great...
|
||||||
&& -dir.z > 0.1
|
&& -dir.z > 0.1
|
||||||
// ...and we're falling/standing OR there is a block *directly* beneath our current origin (note: not hitbox)...
|
// ...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))
|
.get((pos.0 - Vec3::unit_z()).map(|e| e.floor() as i32))
|
||||||
.map(|vox| !vox.is_empty())
|
.map(|vox| !vox.is_empty())
|
||||||
.unwrap_or(false))
|
.unwrap_or(false))
|
||||||
|
@ -490,6 +490,14 @@ impl Server {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
ClientMsg::SwapInventorySlots(a, b) => {
|
||||||
|
state
|
||||||
|
.ecs()
|
||||||
|
.write_storage::<comp::Inventory>()
|
||||||
|
.get_mut(entity)
|
||||||
|
.map(|inv| inv.swap_slots(a, b));
|
||||||
|
state.write_component(entity, comp::InventoryUpdate);
|
||||||
|
}
|
||||||
ClientMsg::Character { name, body } => match client.client_state {
|
ClientMsg::Character { name, body } => match client.client_state {
|
||||||
// Become Registered first.
|
// Become Registered first.
|
||||||
ClientState::Connected => {
|
ClientState::Connected => {
|
||||||
|
@ -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 client::Client;
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
color,
|
||||||
@ -17,10 +17,10 @@ widget_ids! {
|
|||||||
inv_grid_1,
|
inv_grid_1,
|
||||||
inv_grid_2,
|
inv_grid_2,
|
||||||
inv_scrollbar,
|
inv_scrollbar,
|
||||||
inv_slot_0,
|
inv_slots_0,
|
||||||
map_title,
|
map_title,
|
||||||
inv_slot[],
|
inv_slots[],
|
||||||
item1,
|
items[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +51,7 @@ pub struct State {
|
|||||||
const BAG_SCALE: f64 = 4.0;
|
const BAG_SCALE: f64 = 4.0;
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
HudEvent(HudEvent),
|
||||||
Close,
|
Close,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,12 +73,13 @@ impl<'a> Widget for Bag<'a> {
|
|||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
|
|
||||||
let inventory_slots = self
|
let mut event = None;
|
||||||
.client
|
|
||||||
.inventories()
|
let invs = self.client.inventories();
|
||||||
.get(self.client.entity())
|
let inventory = match invs.get(self.client.entity()) {
|
||||||
.map(|inv| inv.slots().len())
|
Some(inv) => inv,
|
||||||
.unwrap_or(0);
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
// Bag parts
|
// Bag parts
|
||||||
Image::new(self.imgs.bag_bot)
|
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)
|
.bottom_right_with_margins_on(ui.window, 60.0, 5.0)
|
||||||
.set(state.ids.bag_bot, ui);
|
.set(state.ids.bag_bot, ui);
|
||||||
Image::new(self.imgs.bag_mid)
|
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)
|
.up_from(state.ids.bag_bot, 0.0)
|
||||||
.set(state.ids.bag_mid, ui);
|
.set(state.ids.bag_mid, ui);
|
||||||
Image::new(self.imgs.bag_top)
|
Image::new(self.imgs.bag_top)
|
||||||
@ -95,7 +97,7 @@ impl<'a> Widget for Bag<'a> {
|
|||||||
|
|
||||||
// Alignment for Grid
|
// Alignment for Grid
|
||||||
Rectangle::fill_with(
|
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,
|
color::TRANSPARENT,
|
||||||
)
|
)
|
||||||
.top_left_with_margins_on(state.ids.bag_top, 9.0 * BAG_SCALE, 3.0 * BAG_SCALE)
|
.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);*/
|
.set(state.ids.inv_scrollbar, ui);*/
|
||||||
|
|
||||||
// Create available inventory slot widgets
|
// Create available inventory slot widgets
|
||||||
if state.ids.inv_slot.len() < inventory_slots {
|
|
||||||
|
if state.ids.inv_slots.len() < inventory.len() {
|
||||||
state.update(|s| {
|
state.update(|s| {
|
||||||
s.ids
|
s.ids
|
||||||
.inv_slot
|
.inv_slots
|
||||||
.resize(inventory_slots, &mut ui.widget_id_generator());
|
.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 x = i % 5;
|
||||||
let y = 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(
|
.top_left_with_margins_on(
|
||||||
state.ids.inv_alignment,
|
state.ids.inv_alignment,
|
||||||
4.0 + y as f64 * (40.0 + 4.0),
|
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...
|
) // conrod uses a (y,x) format for placing...
|
||||||
.parent(state.ids.bag_mid) // Avoids the background overlapping available slots
|
.parent(state.ids.bag_mid) // Avoids the background overlapping available slots
|
||||||
.w_h(40.0, 40.0)
|
.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)));
|
||||||
}
|
}
|
||||||
// Test Item
|
|
||||||
if inventory_slots > 0 {
|
// Item
|
||||||
|
if item.is_some() {
|
||||||
Button::image(self.imgs.potion_red) // TODO: Insert variable image depending on the item displayed in that slot
|
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
|
.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
|
.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("5x") // TODO: Quantity goes here...
|
||||||
.label_font_id(self.fonts.opensans)
|
.label_font_id(self.fonts.opensans)
|
||||||
.label_font_size(12)
|
.label_font_size(12)
|
||||||
.label_x(Relative::Scalar(10.0))
|
.label_x(Relative::Scalar(10.0))
|
||||||
.label_y(Relative::Scalar(-10.0))
|
.label_y(Relative::Scalar(-10.0))
|
||||||
.label_color(TEXT_COLOR)
|
.label_color(TEXT_COLOR)
|
||||||
.set(state.ids.item1, ui); // TODO: Add widget_id generator for displayed items
|
.parent(state.ids.inv_slots[i])
|
||||||
|
.set(state.ids.items[i], ui);
|
||||||
}
|
}
|
||||||
// X-button
|
}
|
||||||
|
|
||||||
|
// Close button
|
||||||
|
|
||||||
if Button::image(self.imgs.close_button)
|
if Button::image(self.imgs.close_button)
|
||||||
.w_h(28.0, 28.0)
|
.w_h(28.0, 28.0)
|
||||||
.hover_image(self.imgs.close_button_hover)
|
.hover_image(self.imgs.close_button_hover)
|
||||||
@ -163,9 +186,9 @@ impl<'a> Widget for Bag<'a> {
|
|||||||
.set(state.ids.bag_close, ui)
|
.set(state.ids.bag_close, ui)
|
||||||
.was_clicked()
|
.was_clicked()
|
||||||
{
|
{
|
||||||
Some(Event::Close)
|
event = Some(Event::Close);
|
||||||
} else {
|
}
|
||||||
None
|
|
||||||
}
|
event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,7 @@ pub enum Event {
|
|||||||
CrosshairType(CrosshairType),
|
CrosshairType(CrosshairType),
|
||||||
UiScale(ScaleChange),
|
UiScale(ScaleChange),
|
||||||
CharacterSelection,
|
CharacterSelection,
|
||||||
|
SwapInventorySlots(usize, usize),
|
||||||
Logout,
|
Logout,
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
@ -589,6 +590,7 @@ impl Hud {
|
|||||||
// Bag contents
|
// Bag contents
|
||||||
if self.show.bag {
|
if self.show.bag {
|
||||||
match Bag::new(client, &self.imgs, &self.fonts).set(self.ids.bag, ui_widgets) {
|
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) => {
|
Some(bag::Event::Close) => {
|
||||||
self.show.bag(false);
|
self.show.bag(false);
|
||||||
self.force_ungrab = true;
|
self.force_ungrab = true;
|
||||||
|
@ -318,6 +318,9 @@ impl PlayState for SessionState {
|
|||||||
global_state.settings.graphics.max_fps = fps;
|
global_state.settings.graphics.max_fps = fps;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state.settings.save_to_file_warn();
|
||||||
}
|
}
|
||||||
|
HudEvent::SwapInventorySlots(a, b) => {
|
||||||
|
self.client.borrow_mut().swap_inventory_slots(a, b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user