mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Trade implementation progress.
- Accept/decline buttons that submit the proper messages - A phase2 screen that renders the (item, quantity) pairs as text - More checks in the trade state machine server-side.
This commit is contained in:
parent
e2b55e0706
commit
abb5684883
@ -4,10 +4,14 @@
|
||||
(
|
||||
string_map: {
|
||||
"hud.trade.trade_window": "Trade window",
|
||||
"hud.trade.phase1_description": "Drag the items you want to trade into your area.",
|
||||
"hud.trade.phase2_description": "The trade is now locked to give you time to review it.",
|
||||
"hud.trade.phase1_description": "Drag the items you want to trade\n into your area.",
|
||||
"hud.trade.phase2_description": "The trade is now locked to give you\n time to review it.",
|
||||
/// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness
|
||||
"hud.trade.phase3_description": "Trade is finalized.",
|
||||
"hud.trade.phase3_description": "Trade is being processed.",
|
||||
"hud.trade.persons_offer": "{playername}'s offer",
|
||||
"hud.trade.has_accepted": "{playername}\nhas accepted",
|
||||
"hud.trade.accept": "Accept",
|
||||
"hud.trade.decline": "Decline",
|
||||
},
|
||||
|
||||
|
||||
|
@ -648,19 +648,13 @@ impl Client {
|
||||
|
||||
pub fn trade_action(&mut self, msg: TradeActionMsg) {
|
||||
if let Some((id, _)) = self.pending_trade {
|
||||
if let TradeActionMsg::Decline = msg {
|
||||
self.pending_trade.take();
|
||||
}
|
||||
self.send_msg(ClientGeneral::UpdatePendingTrade(id, msg));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decline_trade(&mut self) {
|
||||
if let Some((id, _)) = self.pending_trade.take() {
|
||||
self.send_msg(ClientGeneral::UpdatePendingTrade(
|
||||
id,
|
||||
TradeActionMsg::Decline,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dead(&self) -> bool {
|
||||
self.state
|
||||
.ecs()
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::{comp::inventory::slot::InvSlotId, uid::Uid};
|
||||
use crate::{
|
||||
comp::inventory::{slot::InvSlotId, Inventory},
|
||||
uid::Uid,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::warn;
|
||||
@ -65,19 +68,41 @@ impl PendingTrade {
|
||||
.map(|(i, _)| i)
|
||||
}
|
||||
|
||||
pub fn process_msg(&mut self, who: usize, msg: TradeActionMsg) {
|
||||
/// Invariants:
|
||||
/// - A party is never shown as offering more of an item than they own
|
||||
/// - Offers with a quantity of zero get removed from the trade
|
||||
/// - Modifications can only happen in phase 1
|
||||
/// - Whenever a trade is modified, both accept flags get reset (TODO: detect or prevent
|
||||
/// inventory swaps)
|
||||
/// - Accept flags only get set for the current phase
|
||||
pub fn process_msg(&mut self, who: usize, msg: TradeActionMsg, inventory: &Inventory) {
|
||||
use TradeActionMsg::*;
|
||||
match msg {
|
||||
AddItem { item, quantity } => {
|
||||
AddItem {
|
||||
item,
|
||||
quantity: delta,
|
||||
} => {
|
||||
if self.in_phase1() {
|
||||
let total = self.offers[who].entry(item).or_insert(0);
|
||||
*total = total.saturating_add(quantity);
|
||||
if delta > 0 {
|
||||
let total = self.offers[who].entry(item).or_insert(0);
|
||||
let owned_quantity = inventory.get(item).map(|i| i.amount()).unwrap_or(0);
|
||||
*total = total.saturating_add(delta).min(owned_quantity);
|
||||
self.phase1_accepts = [false, false];
|
||||
}
|
||||
}
|
||||
},
|
||||
RemoveItem { item, quantity } => {
|
||||
RemoveItem {
|
||||
item,
|
||||
quantity: delta,
|
||||
} => {
|
||||
if self.in_phase1() {
|
||||
let total = self.offers[who].entry(item).or_insert(0);
|
||||
*total = total.saturating_sub(quantity);
|
||||
self.offers[who]
|
||||
.entry(item)
|
||||
.and_replace_entry_with(|_, mut total| {
|
||||
total = total.saturating_sub(delta);
|
||||
if total > 0 { Some(total) } else { None }
|
||||
});
|
||||
self.phase1_accepts = [false, false];
|
||||
}
|
||||
},
|
||||
Phase1Accept => {
|
||||
@ -109,10 +134,16 @@ impl Trades {
|
||||
id
|
||||
}
|
||||
|
||||
pub fn process_trade_action(&mut self, id: usize, who: Uid, msg: TradeActionMsg) {
|
||||
pub fn process_trade_action(
|
||||
&mut self,
|
||||
id: usize,
|
||||
who: Uid,
|
||||
msg: TradeActionMsg,
|
||||
inventory: &Inventory,
|
||||
) {
|
||||
if let Some(trade) = self.trades.get_mut(&id) {
|
||||
if let Some(party) = trade.which_party(who) {
|
||||
trade.process_msg(party, msg);
|
||||
trade.process_msg(party, msg, inventory);
|
||||
} else {
|
||||
warn!(
|
||||
"An entity who is not a party to trade {} tried to modify it",
|
||||
|
@ -1,5 +1,5 @@
|
||||
use specs::{world::WorldExt, Entity as EcsEntity};
|
||||
use tracing::{error, warn};
|
||||
use tracing::error;
|
||||
|
||||
use common::{
|
||||
comp::{self, agent::AgentEvent, inventory::slot::EquipSlot, item, slot::Slot, Inventory, Pos},
|
||||
|
@ -2,7 +2,6 @@ use crate::{state_ext::StateExt, Server};
|
||||
use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
span,
|
||||
trade::{TradeActionMsg, Trades},
|
||||
};
|
||||
use entity_creation::{
|
||||
handle_beam, handle_create_npc, handle_create_waypoint, handle_initialize_character,
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::{comp::inventory::slot::InvSlotId, events::group_manip::handle_invite, Server};
|
||||
use crate::{events::group_manip::handle_invite, Server};
|
||||
use common::{
|
||||
comp::group::InviteKind,
|
||||
comp::{
|
||||
group::InviteKind,
|
||||
inventory::{Inventory, slot::InvSlotId},
|
||||
},
|
||||
trade::{PendingTrade, TradeActionMsg, Trades},
|
||||
uid::Uid,
|
||||
};
|
||||
@ -30,20 +33,21 @@ pub fn handle_process_trade_action(
|
||||
.and_then(|u| server.state.ecs().entity_from_uid(u.0))
|
||||
.map(|e| server.notify_client(e, ServerGeneral::DeclinedTrade));
|
||||
} else {
|
||||
trades.process_trade_action(trade_id, uid, msg);
|
||||
if let Some(inv) = server.state.ecs().read_component::<Inventory>().get(entity) {
|
||||
trades.process_trade_action(trade_id, uid, msg, inv);
|
||||
}
|
||||
if let Some(trade) = trades.trades.get(&trade_id) {
|
||||
if trade.should_commit() {
|
||||
// TODO: inventory manip
|
||||
} else {
|
||||
// send the updated state to both parties
|
||||
for party in trade.parties.iter() {
|
||||
server.state.ecs().entity_from_uid(party.0).map(|e| {
|
||||
server.notify_client(
|
||||
e,
|
||||
ServerGeneral::UpdatePendingTrade(trade_id, trade.clone()),
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
// send the updated state to both parties
|
||||
for party in trade.parties.iter() {
|
||||
server.state.ecs().entity_from_uid(party.0).map(|e| {
|
||||
server.notify_client(
|
||||
e,
|
||||
ServerGeneral::UpdatePendingTrade(trade_id, trade.clone()),
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ impl<'a> Widget for Group<'a> {
|
||||
.crop_kids()
|
||||
.set(state.ids.bg, ui);
|
||||
}
|
||||
if let Some((_, timeout_start, timeout_dur, kind)) = open_invite {
|
||||
if let Some((_, timeout_start, timeout_dur, _)) = open_invite {
|
||||
// Group Menu button
|
||||
Button::image(self.imgs.group_icon)
|
||||
.w_h(49.0, 26.0)
|
||||
|
@ -44,7 +44,6 @@ use prompt_dialog::PromptDialog;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings_window::{SettingsTab, SettingsWindow};
|
||||
use skillbar::Skillbar;
|
||||
use slots::{InventorySlot, TradeSlot};
|
||||
use social::{Social, SocialTab};
|
||||
use trade::Trade;
|
||||
|
||||
@ -55,7 +54,9 @@ use crate::{
|
||||
render::{Consts, Globals, RenderMode, Renderer},
|
||||
scene::camera::{self, Camera},
|
||||
settings::Fps,
|
||||
ui::{fonts::Fonts, img_ids::Rotations, slot, slot::SlotKey, Graphic, Ingameable, ScaleMode, Ui},
|
||||
ui::{
|
||||
fonts::Fonts, img_ids::Rotations, slot, slot::SlotKey, Graphic, Ingameable, ScaleMode, Ui,
|
||||
},
|
||||
window::{Event as WinEvent, FullScreenSettings, GameInput},
|
||||
GlobalState,
|
||||
};
|
||||
@ -397,7 +398,6 @@ pub enum Event {
|
||||
bypass_dialog: bool,
|
||||
},
|
||||
DropSlot(comp::slot::Slot),
|
||||
DeclineTrade,
|
||||
ChangeHotbarState(Box<HotbarState>),
|
||||
TradeAction(TradeActionMsg),
|
||||
Ability3(bool),
|
||||
@ -2125,24 +2125,24 @@ impl Hud {
|
||||
&self.imgs,
|
||||
&self.item_imgs,
|
||||
&self.fonts,
|
||||
&self.rot_imgs,
|
||||
tooltip_manager,
|
||||
&mut self.slot_manager,
|
||||
i18n,
|
||||
&self.show,
|
||||
)
|
||||
.set(self.ids.trade, ui_widgets)
|
||||
{
|
||||
Some(trade::Event::Close) => {
|
||||
self.show.stats = false;
|
||||
self.show.trade(false);
|
||||
events.push(Event::DeclineTrade);
|
||||
if !self.show.social {
|
||||
self.show.want_grab = true;
|
||||
self.force_ungrab = false;
|
||||
} else {
|
||||
self.force_ungrab = true
|
||||
};
|
||||
Some(msg) => {
|
||||
if let TradeActionMsg::Decline = msg {
|
||||
self.show.stats = false;
|
||||
self.show.trade(false);
|
||||
if !self.show.social {
|
||||
self.show.want_grab = true;
|
||||
self.force_ungrab = false;
|
||||
} else {
|
||||
self.force_ungrab = true
|
||||
};
|
||||
}
|
||||
events.push(Event::TradeAction(msg));
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
@ -2636,7 +2636,7 @@ impl Hud {
|
||||
if let Some(inventory) = inventories.get(entity) {
|
||||
events.push(Event::TradeAction(TradeActionMsg::AddItem {
|
||||
item: i.0,
|
||||
quantity: i.amount(inventory).unwrap_or(0),
|
||||
quantity: i.amount(inventory).unwrap_or(1),
|
||||
}));
|
||||
}
|
||||
} else if let (Trade(t), Inventory(_)) = (a, b) {
|
||||
@ -2644,7 +2644,7 @@ impl Hud {
|
||||
if let Some(invslot) = t.invslot {
|
||||
events.push(Event::TradeAction(TradeActionMsg::RemoveItem {
|
||||
item: invslot,
|
||||
quantity: t.amount(inventory).unwrap_or(0),
|
||||
quantity: t.amount(inventory).unwrap_or(1),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +1,35 @@
|
||||
use super::{
|
||||
cr_color,
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
img_ids::Imgs,
|
||||
item_imgs::ItemImgs,
|
||||
slots::{InventorySlot, SlotManager, TradeSlot},
|
||||
util::loadout_slot_text,
|
||||
Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, QUALITY_COMMON, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
slots::{SlotManager, TradeSlot},
|
||||
TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
};
|
||||
use crate::{
|
||||
hud::{get_quality_col, slots::SlotKind},
|
||||
i18n::Localization,
|
||||
ui::{
|
||||
fonts::Fonts,
|
||||
slot::{ContentSize, SlotMaker},
|
||||
ImageFrame, Tooltip, TooltipManager, Tooltipable,
|
||||
TooltipManager,
|
||||
},
|
||||
};
|
||||
use client::Client;
|
||||
use common::{comp::item::Quality, trade::PendingTrade};
|
||||
use common::{
|
||||
comp::Inventory,
|
||||
trade::{PendingTrade, TradeActionMsg},
|
||||
};
|
||||
use common_net::sync::WorldSyncExt;
|
||||
use conrod_core::{
|
||||
color,
|
||||
widget::{self, Button, Image, Rectangle, Scrollbar, State as ConrodState, Text},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, WidgetCommon,
|
||||
position::Relative,
|
||||
widget::{self, Button, Image, Rectangle, State as ConrodState, Text},
|
||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon,
|
||||
};
|
||||
use inline_tweak::tweak;
|
||||
use vek::*;
|
||||
|
||||
pub struct State {
|
||||
ids: Ids,
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
Close,
|
||||
}
|
||||
|
||||
widget_ids! {
|
||||
pub struct Ids {
|
||||
trade_close,
|
||||
@ -43,8 +39,12 @@ widget_ids! {
|
||||
trade_title,
|
||||
inv_alignment[],
|
||||
inv_slots[],
|
||||
inv_textslots[],
|
||||
offer_headers[],
|
||||
accept_indicators[],
|
||||
phase_indicator,
|
||||
accept_button,
|
||||
decline_button,
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +56,9 @@ pub struct Trade<'a> {
|
||||
fonts: &'a Fonts,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
rot_imgs: &'a ImgsRot,
|
||||
tooltip_manager: &'a mut TooltipManager,
|
||||
//tooltip_manager: &'a mut TooltipManager,
|
||||
slot_manager: &'a mut SlotManager,
|
||||
localized_strings: &'a Localization,
|
||||
show: &'a Show,
|
||||
}
|
||||
|
||||
impl<'a> Trade<'a> {
|
||||
@ -69,11 +67,9 @@ impl<'a> Trade<'a> {
|
||||
imgs: &'a Imgs,
|
||||
item_imgs: &'a ItemImgs,
|
||||
fonts: &'a Fonts,
|
||||
rot_imgs: &'a ImgsRot,
|
||||
tooltip_manager: &'a mut TooltipManager,
|
||||
_tooltip_manager: &'a mut TooltipManager,
|
||||
slot_manager: &'a mut SlotManager,
|
||||
localized_strings: &'a Localization,
|
||||
show: &'a Show,
|
||||
) -> Self {
|
||||
Self {
|
||||
client,
|
||||
@ -81,24 +77,23 @@ impl<'a> Trade<'a> {
|
||||
item_imgs,
|
||||
fonts,
|
||||
common: widget::CommonBuilder::default(),
|
||||
rot_imgs,
|
||||
tooltip_manager,
|
||||
//tooltip_manager,
|
||||
slot_manager,
|
||||
localized_strings,
|
||||
show,
|
||||
}
|
||||
}
|
||||
}
|
||||
const MAX_TRADE_SLOTS: usize = 16;
|
||||
|
||||
impl<'a> Trade<'a> {
|
||||
fn background(&mut self, state: &mut ConrodState<'_, State>, ui: &mut UiCell<'_>) {
|
||||
Image::new(self.imgs.inv_bg_bag)
|
||||
.w_h(tweak!(424.0), 708.0)
|
||||
.w_h(424.0, 708.0)
|
||||
.middle()
|
||||
.color(Some(UI_MAIN))
|
||||
.set(state.ids.bg, ui);
|
||||
Image::new(self.imgs.inv_frame_bag)
|
||||
.w_h(tweak!(424.0), 708.0)
|
||||
.w_h(424.0, 708.0)
|
||||
.middle_of(state.ids.bg)
|
||||
.color(Some(UI_HIGHLIGHT_0))
|
||||
.set(state.ids.bg_frame, ui);
|
||||
@ -153,6 +148,82 @@ impl<'a> Trade<'a> {
|
||||
let entity = self.client.state().ecs().entity_from_uid(uid.0)?;
|
||||
let inventory = inventories.get(entity)?;
|
||||
|
||||
// Alignment for Grid
|
||||
let mut alignment = Rectangle::fill_with([200.0, 340.0], color::TRANSPARENT);
|
||||
if who % 2 == 0 {
|
||||
alignment =
|
||||
alignment.top_left_with_margins_on(state.ids.bg, 180.0, 46.5);
|
||||
} else {
|
||||
alignment = alignment.right_from(state.ids.inv_alignment[0], 0.0);
|
||||
}
|
||||
alignment
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.inv_alignment[who], ui);
|
||||
|
||||
let name = self
|
||||
.client
|
||||
.player_list()
|
||||
.get(&uid)
|
||||
.map(|info| info.player_alias.clone())
|
||||
.unwrap_or_else(|| format!("Player {}", who));
|
||||
|
||||
let offer_header = self
|
||||
.localized_strings
|
||||
.get("hud.trade.persons_offer")
|
||||
.replace("{playername}", &name);
|
||||
Text::new(&offer_header)
|
||||
.up_from(state.ids.inv_alignment[who], 20.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(20))
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
|
||||
.set(state.ids.offer_headers[who], ui);
|
||||
|
||||
let has_accepted = (trade.in_phase1() && trade.phase1_accepts[who])
|
||||
|| (trade.in_phase2() && trade.phase2_accepts[who]);
|
||||
let accept_indicator = self
|
||||
.localized_strings
|
||||
.get("hud.trade.has_accepted")
|
||||
.replace("{playername}", &name);
|
||||
Text::new(&accept_indicator)
|
||||
.down_from(state.ids.inv_alignment[who], 20.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(20))
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, if has_accepted { 1.0 } else { 0.0 }))
|
||||
.set(state.ids.accept_indicators[who], ui);
|
||||
|
||||
|
||||
let mut invslots: Vec<_> = trade.offers[who]
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect();
|
||||
invslots.sort();
|
||||
let tradeslots: Vec<_> = invslots
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, (k, quantity))| TradeSlot {
|
||||
index,
|
||||
quantity,
|
||||
invslot: Some(k),
|
||||
})
|
||||
.collect();
|
||||
|
||||
if trade.in_phase1() {
|
||||
self.phase1_itemwidget(state, ui, inventory, who, &tradeslots);
|
||||
} else {
|
||||
self.phase2_itemwidget(state, ui, inventory, who, &tradeslots);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn phase1_itemwidget(
|
||||
&mut self,
|
||||
state: &mut ConrodState<'_, State>,
|
||||
ui: &mut UiCell<'_>,
|
||||
inventory: &Inventory,
|
||||
who: usize,
|
||||
tradeslots: &Vec<TradeSlot>,
|
||||
) {
|
||||
let mut slot_maker = SlotMaker {
|
||||
empty_slot: self.imgs.inv_slot,
|
||||
filled_slot: self.imgs.inv_slot,
|
||||
@ -171,26 +242,7 @@ impl<'a> Trade<'a> {
|
||||
image_source: self.item_imgs,
|
||||
slot_manager: Some(self.slot_manager),
|
||||
};
|
||||
// Alignment for Grid
|
||||
let mut alignment = Rectangle::fill_with([200.0, 600.0], color::TRANSPARENT);
|
||||
if who % 2 == 0 {
|
||||
alignment =
|
||||
alignment.top_left_with_margins_on(state.ids.bg, tweak!(160.0), tweak!(46.5));
|
||||
} else {
|
||||
alignment = alignment.right_from(state.ids.inv_alignment[0], 0.0);
|
||||
}
|
||||
alignment
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.inv_alignment[who], ui);
|
||||
|
||||
Text::new(&format!("Player {}'s offer", who))
|
||||
.up_from(state.ids.inv_alignment[who], 20.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(20))
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
|
||||
.set(state.ids.offer_headers[who], ui);
|
||||
|
||||
const MAX_TRADE_SLOTS: usize = 16;
|
||||
if state.ids.inv_slots.len() < 2 * MAX_TRADE_SLOTS {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
@ -199,21 +251,18 @@ impl<'a> Trade<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
let mut invslots: Vec<_> = trade.offers[who].iter().map(|(k, v)| (k.clone(), v.clone())).collect();
|
||||
invslots.sort();
|
||||
let tradeslots: Vec<_> = invslots.into_iter().enumerate().map(|(index, (k, quantity))| TradeSlot { index, quantity, invslot: Some(k) }).collect();
|
||||
|
||||
for i in 0..MAX_TRADE_SLOTS {
|
||||
let x = i % 4;
|
||||
let y = i / 4;
|
||||
|
||||
let slot = tradeslots.get(i).cloned().unwrap_or(TradeSlot { index: i, quantity: 0, invslot: None, });
|
||||
let slot = tradeslots.get(i).cloned().unwrap_or(TradeSlot {
|
||||
index: i,
|
||||
quantity: 0,
|
||||
invslot: None,
|
||||
});
|
||||
// Slot
|
||||
let mut slot_widget = slot_maker
|
||||
.fabricate(
|
||||
slot.clone(),
|
||||
[40.0; 2],
|
||||
)
|
||||
let slot_widget = slot_maker
|
||||
.fabricate(slot.clone(), [40.0; 2])
|
||||
.top_left_with_margins_on(
|
||||
state.ids.inv_alignment[who],
|
||||
0.0 + y as f64 * (40.0),
|
||||
@ -221,7 +270,86 @@ impl<'a> Trade<'a> {
|
||||
);
|
||||
slot_widget.set(state.ids.inv_slots[i + who * MAX_TRADE_SLOTS], ui);
|
||||
}
|
||||
None
|
||||
}
|
||||
fn phase2_itemwidget(
|
||||
&mut self,
|
||||
state: &mut ConrodState<'_, State>,
|
||||
ui: &mut UiCell<'_>,
|
||||
inventory: &Inventory,
|
||||
who: usize,
|
||||
tradeslots: &Vec<TradeSlot>,
|
||||
) {
|
||||
if state.ids.inv_textslots.len() < 2 * MAX_TRADE_SLOTS {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.inv_textslots
|
||||
.resize(2 * MAX_TRADE_SLOTS, &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
for i in 0..MAX_TRADE_SLOTS {
|
||||
let slot = tradeslots.get(i).cloned().unwrap_or(TradeSlot {
|
||||
index: i,
|
||||
quantity: 0,
|
||||
invslot: None,
|
||||
});
|
||||
let itemname = slot
|
||||
.invslot
|
||||
.and_then(|i| inventory.get(i))
|
||||
.map(|i| i.name())
|
||||
.unwrap_or("");
|
||||
let is_present = slot.quantity > 0 && slot.invslot.is_some();
|
||||
Text::new(&format!("{} x {}", slot.quantity, itemname))
|
||||
.top_left_with_margins_on(state.ids.inv_alignment[who], 10.0 + i as f64 * 30.0, 0.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(20))
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, if is_present { 1.0 } else { 0.0 }))
|
||||
.set(state.ids.inv_textslots[i + who * MAX_TRADE_SLOTS], ui);
|
||||
}
|
||||
}
|
||||
|
||||
fn accept_decline_buttons(
|
||||
&mut self,
|
||||
state: &mut ConrodState<'_, State>,
|
||||
ui: &mut UiCell<'_>,
|
||||
trade: &'a PendingTrade,
|
||||
) -> <Self as Widget>::Event {
|
||||
let mut event = None;
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(31.0 * 5.0, 12.0 * 2.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.bottom_left_with_margins_on(state.ids.bg, 80.0, 60.0)
|
||||
.label(&self.localized_strings.get("hud.trade.accept"))
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.set(state.ids.accept_button, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
if trade.in_phase1() {
|
||||
event = Some(TradeActionMsg::Phase1Accept);
|
||||
} else if trade.in_phase2() {
|
||||
event = Some(TradeActionMsg::Phase2Accept);
|
||||
}
|
||||
}
|
||||
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(31.0 * 5.0, 12.0 * 2.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.right_from(state.ids.accept_button, 20.0)
|
||||
.label(&self.localized_strings.get("hud.trade.decline"))
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.set(state.ids.decline_button, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
event = Some(TradeActionMsg::Decline);
|
||||
}
|
||||
event
|
||||
}
|
||||
|
||||
fn close_button(
|
||||
@ -230,14 +358,14 @@ impl<'a> Trade<'a> {
|
||||
ui: &mut UiCell<'_>,
|
||||
) -> <Self as Widget>::Event {
|
||||
if Button::image(self.imgs.close_btn)
|
||||
.w_h(tweak!(24.0), 25.0)
|
||||
.w_h(24.0, 25.0)
|
||||
.hover_image(self.imgs.close_btn_hover)
|
||||
.press_image(self.imgs.close_btn_press)
|
||||
.top_right_with_margins_on(state.ids.bg, 0.0, 0.0)
|
||||
.set(state.ids.trade_close, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
Some(Event::Close)
|
||||
Some(TradeActionMsg::Decline)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -245,7 +373,7 @@ impl<'a> Trade<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Widget for Trade<'a> {
|
||||
type Event = Option<Event>;
|
||||
type Event = Option<TradeActionMsg>;
|
||||
type State = State;
|
||||
type Style = ();
|
||||
|
||||
@ -263,7 +391,7 @@ impl<'a> Widget for Trade<'a> {
|
||||
let mut event = None;
|
||||
let trade = match self.client.pending_trade() {
|
||||
Some((_, trade)) => trade,
|
||||
None => return Some(Event::Close),
|
||||
None => return Some(TradeActionMsg::Decline),
|
||||
};
|
||||
|
||||
if state.ids.inv_alignment.len() < 2 {
|
||||
@ -276,8 +404,14 @@ impl<'a> Widget for Trade<'a> {
|
||||
s.ids.offer_headers.resize(2, &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
if state.ids.accept_indicators.len() < 2 {
|
||||
state.update(|s| {
|
||||
s.ids.accept_indicators.resize(2, &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
|
||||
let trade_tooltip = Tooltip::new({
|
||||
// TODO: item tooltips in trade preview
|
||||
/*let trade_tooltip = Tooltip::new({
|
||||
// Edge images [t, b, r, l]
|
||||
// Corner images [tr, tl, br, bl]
|
||||
let edge = &self.rot_imgs.tt_side;
|
||||
@ -293,7 +427,7 @@ impl<'a> Widget for Trade<'a> {
|
||||
.parent(ui.window)
|
||||
.desc_font_size(self.fonts.cyri.scale(12))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.desc_text_color(TEXT_COLOR);
|
||||
.desc_text_color(TEXT_COLOR);*/
|
||||
|
||||
self.background(&mut state, ui);
|
||||
self.title(&mut state, ui);
|
||||
@ -301,7 +435,9 @@ impl<'a> Widget for Trade<'a> {
|
||||
|
||||
event = self.item_pane(&mut state, ui, &trade, 0).or(event);
|
||||
event = self.item_pane(&mut state, ui, &trade, 1).or(event);
|
||||
// Close button
|
||||
event = self
|
||||
.accept_decline_buttons(&mut state, ui, &trade)
|
||||
.or(event);
|
||||
event = self.close_button(&mut state, ui).or(event);
|
||||
|
||||
event
|
||||
|
@ -1117,10 +1117,6 @@ impl PlayState for SessionState {
|
||||
client.disable_lantern();
|
||||
}
|
||||
},
|
||||
HudEvent::DeclineTrade => {
|
||||
let mut client = self.client.borrow_mut();
|
||||
client.decline_trade();
|
||||
},
|
||||
HudEvent::ChangeHotbarState(state) => {
|
||||
let client = self.client.borrow();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user