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:
parent
123a78552a
commit
31f8794c39
@ -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<u32> {
|
||||
self.view_distance
|
||||
}
|
||||
|
@ -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<Self>;
|
||||
}
|
||||
|
@ -17,6 +17,20 @@ impl Inventory {
|
||||
&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
|
||||
pub fn get(&self, cell: usize) -> Option<Item> {
|
||||
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<Item> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ pub enum ClientMsg {
|
||||
vel: comp::Vel,
|
||||
ori: comp::Ori,
|
||||
},
|
||||
SwapInventorySlots(usize, usize),
|
||||
TerrainChunkRequest {
|
||||
key: Vec2<i32>,
|
||||
},
|
||||
|
@ -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))
|
||||
|
@ -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 {
|
||||
// Become Registered first.
|
||||
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 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>) -> 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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user