mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Trade implementation progress.
- Server messages now bring up the trade window. - When a trade is declined, it closes the window on both clients.
This commit is contained in:
parent
ae528124fc
commit
aeb2398fc6
@ -32,6 +32,7 @@ use common::{
|
||||
recipe::RecipeBook,
|
||||
span,
|
||||
terrain::{block::Block, neighbors, BiomeKind, SitesKind, TerrainChunk, TerrainChunkSize},
|
||||
trade::{PendingTrade, TradeActionMsg},
|
||||
uid::{Uid, UidAllocator},
|
||||
vol::RectVolSize,
|
||||
};
|
||||
@ -141,6 +142,8 @@ pub struct Client {
|
||||
group_members: HashMap<Uid, group::Role>,
|
||||
// Pending invites that this client has sent out
|
||||
pending_invites: HashSet<Uid>,
|
||||
// The pending trade the client is involved in, and it's id
|
||||
pending_trade: Option<(usize, PendingTrade)>,
|
||||
|
||||
_network: Network,
|
||||
participant: Option<Participant>,
|
||||
@ -429,6 +432,7 @@ impl Client {
|
||||
group_leader: None,
|
||||
group_members: HashMap::new(),
|
||||
pending_invites: HashSet::new(),
|
||||
pending_trade: None,
|
||||
|
||||
_network: network,
|
||||
participant: Some(participant),
|
||||
@ -642,6 +646,15 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
@ -766,6 +779,8 @@ impl Client {
|
||||
|
||||
pub fn pending_invites(&self) -> &HashSet<Uid> { &self.pending_invites }
|
||||
|
||||
pub fn pending_trade(&self) -> &Option<(usize, PendingTrade)> { &self.pending_trade }
|
||||
|
||||
pub fn send_group_invite(&mut self, invitee: Uid) {
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::Invite(invitee),
|
||||
@ -1559,6 +1574,13 @@ impl Client {
|
||||
impulse,
|
||||
});
|
||||
},
|
||||
ServerGeneral::UpdatePendingTrade(id, trade) => {
|
||||
tracing::info!("UpdatePendingTrade {:?} {:?}", id, trade);
|
||||
self.pending_trade = Some((id, trade));
|
||||
},
|
||||
ServerGeneral::DeclinedTrade => {
|
||||
self.pending_trade = None;
|
||||
},
|
||||
_ => unreachable!("Not a in_game message"),
|
||||
}
|
||||
Ok(())
|
||||
|
@ -7,8 +7,8 @@ use common::{
|
||||
outcome::Outcome,
|
||||
recipe::RecipeBook,
|
||||
resources::TimeOfDay,
|
||||
trade::PendingTrade,
|
||||
terrain::{Block, TerrainChunk},
|
||||
trade::PendingTrade,
|
||||
uid::Uid,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
@ -124,6 +124,7 @@ pub enum ServerGeneral {
|
||||
/// Send a popup notification such as "Waypoint Saved"
|
||||
Notification(Notification),
|
||||
UpdatePendingTrade(usize, PendingTrade),
|
||||
DeclinedTrade,
|
||||
}
|
||||
|
||||
impl ServerGeneral {
|
||||
@ -230,7 +231,8 @@ impl ServerMsg {
|
||||
| ServerGeneral::SetViewDistance(_)
|
||||
| ServerGeneral::Outcomes(_)
|
||||
| ServerGeneral::Knockback(_)
|
||||
| ServerGeneral::UpdatePendingTrade(_, _) => {
|
||||
| ServerGeneral::UpdatePendingTrade(_, _)
|
||||
| ServerGeneral::DeclinedTrade => {
|
||||
c_type == ClientType::Game && presence.is_some()
|
||||
},
|
||||
// Always possible
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::{character::CharacterId, comp, rtsim::RtSimEntity, uid::Uid, util::Dir, Explosion};
|
||||
use crate::{
|
||||
character::CharacterId, comp, rtsim::RtSimEntity, trade::TradeActionMsg, uid::Uid, util::Dir,
|
||||
Explosion,
|
||||
};
|
||||
use comp::{
|
||||
item::{Item, Reagent},
|
||||
Ori, Pos,
|
||||
@ -80,6 +83,7 @@ pub enum ServerEvent {
|
||||
DisableLantern(EcsEntity),
|
||||
NpcInteract(EcsEntity, EcsEntity),
|
||||
InitiateTrade(EcsEntity, EcsEntity),
|
||||
ProcessTradeAction(EcsEntity, usize, TradeActionMsg),
|
||||
Mount(EcsEntity, EcsEntity),
|
||||
Unmount(EcsEntity),
|
||||
Possess(Uid, Uid),
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::{comp::inventory::slot::InvSlotId, uid::Uid};
|
||||
use crate::{
|
||||
comp::inventory::slot::InvSlotId,
|
||||
uid::Uid,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::warn;
|
||||
@ -12,6 +15,7 @@ pub enum TradeActionMsg {
|
||||
RemoveItem { item: InvSlotId, quantity: usize },
|
||||
Phase1Accept,
|
||||
Phase2Accept,
|
||||
Decline,
|
||||
}
|
||||
|
||||
/// Items are not removed from the inventory during a PendingTrade: all the
|
||||
@ -45,11 +49,15 @@ impl PendingTrade {
|
||||
pub fn in_phase1(&self) -> bool { !self.phase1_accepts[0] || !self.phase1_accepts[1] }
|
||||
|
||||
pub fn in_phase2(&self) -> bool {
|
||||
(self.phase1_accepts[0] && self.phase1_accepts[1]) && (!self.phase2_accepts[0] || !self.phase2_accepts[1])
|
||||
(self.phase1_accepts[0] && self.phase1_accepts[1])
|
||||
&& (!self.phase2_accepts[0] || !self.phase2_accepts[1])
|
||||
}
|
||||
|
||||
pub fn should_commit(&self) -> bool {
|
||||
self.phase1_accepts[0] && self.phase1_accepts[1] && self.phase2_accepts[0] && self.phase2_accepts[1]
|
||||
self.phase1_accepts[0]
|
||||
&& self.phase1_accepts[1]
|
||||
&& self.phase2_accepts[0]
|
||||
&& self.phase2_accepts[1]
|
||||
}
|
||||
|
||||
pub fn which_party(&self, party: Uid) -> Option<usize> {
|
||||
@ -85,6 +93,7 @@ impl PendingTrade {
|
||||
self.phase2_accepts[who] = true;
|
||||
}
|
||||
},
|
||||
Decline => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,23 +117,37 @@ impl Trades {
|
||||
if let Some(party) = trade.which_party(who) {
|
||||
trade.process_msg(party, msg);
|
||||
} else {
|
||||
warn!("An entity who is not a party to trade {} tried to modify it", id);
|
||||
warn!(
|
||||
"An entity who is not a party to trade {} tried to modify it",
|
||||
id
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warn!("Attempt to modify nonexistent trade id {}", id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decline_trade(&mut self, id: usize, who: Uid) {
|
||||
pub fn decline_trade(&mut self, id: usize, who: Uid) -> Option<Uid> {
|
||||
let mut to_notify = None;
|
||||
if let Some(trade) = self.trades.remove(&id) {
|
||||
if let None = trade.which_party(who) {
|
||||
warn!("An entity who is not a party to trade {} tried to decline it", id);
|
||||
// put it back
|
||||
self.trades.insert(id, trade);
|
||||
match trade.which_party(who) {
|
||||
Some(i) => {
|
||||
// let the other person know the trade was declined
|
||||
to_notify = Some(trade.parties[1 - i])
|
||||
},
|
||||
None => {
|
||||
warn!(
|
||||
"An entity who is not a party to trade {} tried to decline it",
|
||||
id
|
||||
);
|
||||
// put it back
|
||||
self.trades.insert(id, trade);
|
||||
},
|
||||
}
|
||||
} else {
|
||||
warn!("Attempt to decline nonexistent trade id {}", id);
|
||||
}
|
||||
to_notify
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,8 @@ impl Client {
|
||||
| ServerGeneral::SetViewDistance(_)
|
||||
| ServerGeneral::Outcomes(_)
|
||||
| ServerGeneral::Knockback(_)
|
||||
| ServerGeneral::UpdatePendingTrade(_, _) => {
|
||||
| ServerGeneral::UpdatePendingTrade(_, _)
|
||||
| ServerGeneral::DeclinedTrade => {
|
||||
self.in_game_stream.try_lock().unwrap().send(g)
|
||||
},
|
||||
// Always possible
|
||||
@ -168,7 +169,8 @@ impl Client {
|
||||
| ServerGeneral::SetViewDistance(_)
|
||||
| ServerGeneral::Outcomes(_)
|
||||
| ServerGeneral::Knockback(_)
|
||||
| ServerGeneral::UpdatePendingTrade(_, _) => {
|
||||
| ServerGeneral::UpdatePendingTrade(_, _)
|
||||
| ServerGeneral::DeclinedTrade => {
|
||||
PreparedMsg::new(2, &g, &self.in_game_stream)
|
||||
},
|
||||
// Always possible
|
||||
|
@ -240,12 +240,18 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
);
|
||||
},
|
||||
InviteKind::Trade => {
|
||||
if let (Some(inviter_uid), Some(invitee_uid)) = (uids.get(inviter).copied(), uids.get(entity).copied()) {
|
||||
if let (Some(inviter_uid), Some(invitee_uid)) =
|
||||
(uids.get(inviter).copied(), uids.get(entity).copied())
|
||||
{
|
||||
let mut trades = state.ecs().write_resource::<Trades>();
|
||||
let id = trades.begin_trade(inviter_uid, invitee_uid);
|
||||
let trade = trades.trades[&id].clone();
|
||||
clients.get(inviter).map(|c| c.send(ServerGeneral::UpdatePendingTrade(id, trade.clone())));
|
||||
clients.get(entity).map(|c| c.send(ServerGeneral::UpdatePendingTrade(id, trade)));
|
||||
clients.get(inviter).map(|c| {
|
||||
c.send(ServerGeneral::UpdatePendingTrade(id, trade.clone()))
|
||||
});
|
||||
clients
|
||||
.get(entity)
|
||||
.map(|c| c.send(ServerGeneral::UpdatePendingTrade(id, trade)));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -72,14 +72,6 @@ pub fn handle_npc_interaction(server: &mut Server, interactor: EcsEntity, npc_en
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_initiate_trade(server: &mut Server, interactor: EcsEntity, counterparty: EcsEntity) {
|
||||
if let Some(uid) = server.state_mut().ecs().uid_from_entity(counterparty) {
|
||||
handle_invite(server, interactor, uid, InviteKind::Trade);
|
||||
} else {
|
||||
warn!("Entity tried to trade with an entity that lacks an uid");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mount(server: &mut Server, mounter: EcsEntity, mountee: EcsEntity) {
|
||||
let state = server.state_mut();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{state_ext::StateExt, Server};
|
||||
use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
trade::{Trades, TradeActionMsg},
|
||||
span,
|
||||
};
|
||||
use entity_creation::{
|
||||
@ -13,12 +14,13 @@ use entity_manipulation::{
|
||||
};
|
||||
use group_manip::handle_group;
|
||||
use interaction::{
|
||||
handle_initiate_trade, handle_lantern, handle_mount, handle_npc_interaction, handle_possess,
|
||||
handle_lantern, handle_mount, handle_npc_interaction, handle_possess,
|
||||
handle_unmount,
|
||||
};
|
||||
use inventory_manip::handle_inventory;
|
||||
use player::{handle_client_disconnect, handle_exit_ingame};
|
||||
use specs::{Entity as EcsEntity, WorldExt};
|
||||
use trade::{handle_initiate_trade, handle_process_trade_action};
|
||||
|
||||
mod entity_creation;
|
||||
mod entity_manipulation;
|
||||
@ -26,6 +28,7 @@ mod group_manip;
|
||||
mod interaction;
|
||||
mod inventory_manip;
|
||||
mod player;
|
||||
mod trade;
|
||||
|
||||
pub enum Event {
|
||||
ClientConnected {
|
||||
@ -107,6 +110,9 @@ impl Server {
|
||||
ServerEvent::InitiateTrade(interactor, target) => {
|
||||
handle_initiate_trade(self, interactor, target)
|
||||
},
|
||||
ServerEvent::ProcessTradeAction(entity, trade_id, msg) => {
|
||||
handle_process_trade_action(self, entity, trade_id, msg);
|
||||
},
|
||||
ServerEvent::Mount(mounter, mountee) => handle_mount(self, mounter, mountee),
|
||||
ServerEvent::Unmount(mounter) => handle_unmount(self, mounter),
|
||||
ServerEvent::Possess(possessor_uid, possesse_uid) => {
|
||||
|
43
server/src/events/trade.rs
Normal file
43
server/src/events/trade.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use crate::{
|
||||
Server,
|
||||
comp::inventory::slot::InvSlotId,
|
||||
events::group_manip::handle_invite,
|
||||
};
|
||||
use common::{
|
||||
comp::{
|
||||
group::InviteKind,
|
||||
},
|
||||
trade::{Trades, TradeActionMsg, PendingTrade},
|
||||
uid::Uid,
|
||||
};
|
||||
use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
|
||||
use specs::{world::WorldExt, Entity as EcsEntity};
|
||||
use tracing::warn;
|
||||
|
||||
|
||||
pub fn handle_initiate_trade(server: &mut Server, interactor: EcsEntity, counterparty: EcsEntity) {
|
||||
if let Some(uid) = server.state_mut().ecs().uid_from_entity(counterparty) {
|
||||
handle_invite(server, interactor, uid, InviteKind::Trade);
|
||||
} else {
|
||||
warn!("Entity tried to trade with an entity that lacks an uid");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_process_trade_action(server: &mut Server, entity: EcsEntity, trade_id: usize, msg: TradeActionMsg) {
|
||||
if let Some(uid) = server.state.ecs().uid_from_entity(entity) {
|
||||
let mut trades = server.state.ecs().write_resource::<Trades>();
|
||||
if let TradeActionMsg::Decline = msg {
|
||||
let to_notify = trades.decline_trade(trade_id, uid);
|
||||
to_notify
|
||||
.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(trade) = trades.trades.get(&trade_id) {
|
||||
if trade.should_commit() {
|
||||
// TODO: inventory manip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -158,6 +158,10 @@ impl Sys {
|
||||
.get_mut(entity)
|
||||
.map(|mut s| s.skill_set.unlock_skill_group(skill_group_kind));
|
||||
},
|
||||
ClientGeneral::UpdatePendingTrade(trade_id, msg) => {
|
||||
tracing::info!("UpdatePendingTrade {:?} {:?}", trade_id, msg);
|
||||
server_emitter.emit(ServerEvent::ProcessTradeAction(entity, trade_id, msg));
|
||||
},
|
||||
_ => unreachable!("not a client_in_game msg"),
|
||||
}
|
||||
Ok(())
|
||||
|
@ -395,6 +395,7 @@ pub enum Event {
|
||||
bypass_dialog: bool,
|
||||
},
|
||||
DropSlot(comp::slot::Slot),
|
||||
DeclineTrade,
|
||||
ChangeHotbarState(Box<HotbarState>),
|
||||
Ability3(bool),
|
||||
Logout,
|
||||
@ -874,6 +875,11 @@ impl Hud {
|
||||
let inventories = ecs.read_storage::<comp::Inventory>();
|
||||
let entities = ecs.entities();
|
||||
let me = client.entity();
|
||||
|
||||
if (client.pending_trade().is_some() && !self.show.trade) || (client.pending_trade().is_none() && self.show.trade) {
|
||||
self.show.toggle_trade();
|
||||
}
|
||||
|
||||
//self.input = client.read_storage::<comp::ControllerInputs>();
|
||||
if let Some(health) = healths.get(me) {
|
||||
// Hurt Frame
|
||||
@ -2125,6 +2131,7 @@ impl Hud {
|
||||
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;
|
||||
|
@ -149,6 +149,17 @@ impl<'a> Widget for Trade<'a> {
|
||||
.font_size(self.fonts.cyri.scale(20))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.trade_title, ui);
|
||||
// Close button
|
||||
if Button::image(self.imgs.close_btn)
|
||||
.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()
|
||||
{
|
||||
event = Some(Event::Close);
|
||||
}
|
||||
|
||||
event
|
||||
}
|
||||
|
@ -1117,6 +1117,10 @@ 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