diff --git a/assets/voxygen/i18n/en/hud/trade.ron b/assets/voxygen/i18n/en/hud/trade.ron index e12fbf4f15..af1e09aaa6 100644 --- a/assets/voxygen/i18n/en/hud/trade.ron +++ b/assets/voxygen/i18n/en/hud/trade.ron @@ -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", }, diff --git a/client/src/lib.rs b/client/src/lib.rs index 1240c16760..428e9caf86 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -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() diff --git a/common/src/trade.rs b/common/src/trade.rs index 5a43dbee34..e53ad9c9ff 100644 --- a/common/src/trade.rs +++ b/common/src/trade.rs @@ -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", diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index b3e0f5e763..bf69e76cd1 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -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}, diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index 042c7a5c03..a163439245 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -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, diff --git a/server/src/events/trade.rs b/server/src/events/trade.rs index 1f49cb8dbc..8a5a5a327b 100644 --- a/server/src/events/trade.rs +++ b/server/src/events/trade.rs @@ -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::().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()), + ) + }); } } } diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index c7b5872249..fcc40b1e13 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -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) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 6eed2ccd97..2c32cd7318 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -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), 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), })); } } diff --git a/voxygen/src/hud/trade.rs b/voxygen/src/hud/trade.rs index d9c599ab1d..9794e8b395 100644 --- a/voxygen/src/hud/trade.rs +++ b/voxygen/src/hud/trade.rs @@ -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, + ) { 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, + ) { + 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, + ) -> ::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<'_>, ) -> ::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; + type Event = Option; 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 diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 7e56999739..a6e41c96f3 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -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();