You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.0 KiB
132 lines
4.0 KiB
use std::collections::HashMap;
|
|
use networking::serverstate::ClientId;
|
|
use items;
|
|
use async_std::sync::{Arc, Mutex, MutexGuard};
|
|
use futures::future::{Future, OptionFuture};
|
|
use items::trade::TradeItem;
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
pub enum TradeStatus {
|
|
SentRequest,
|
|
ReceivedRequest,
|
|
Trading,
|
|
Confirmed,
|
|
FinalConfirm,
|
|
ItemsChecked,
|
|
TradeComplete,
|
|
}
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ClientTradeState {
|
|
client: ClientId,
|
|
other_client: ClientId,
|
|
pub items: Vec<TradeItem>,
|
|
pub meseta: usize,
|
|
pub status: TradeStatus,
|
|
}
|
|
|
|
|
|
impl ClientTradeState {
|
|
pub fn client(&self) -> ClientId {
|
|
self.client
|
|
}
|
|
|
|
pub fn other_client(&self) -> ClientId {
|
|
self.other_client
|
|
}
|
|
}
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum TradeStateError {
|
|
#[error("client not in trade {0}")]
|
|
ClientNotInTrade(ClientId),
|
|
#[error("mismatched trade {0} {1}")]
|
|
MismatchedTrade(ClientId, ClientId),
|
|
}
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct TradeState {
|
|
trades: HashMap<ClientId, Arc<Mutex<ClientTradeState>>>,
|
|
}
|
|
|
|
impl TradeState {
|
|
pub fn new_trade(&mut self, sender: &ClientId, receiver: &ClientId) {
|
|
let state = ClientTradeState {
|
|
client: *sender,
|
|
other_client: *receiver,
|
|
items: Default::default(),
|
|
meseta: 0,
|
|
status: TradeStatus::SentRequest,
|
|
};
|
|
self.trades.insert(*sender, Arc::new(Mutex::new(state)));
|
|
|
|
let state = ClientTradeState {
|
|
client: *receiver,
|
|
other_client: *sender,
|
|
items: Default::default(),
|
|
meseta: 0,
|
|
status: TradeStatus::ReceivedRequest,
|
|
};
|
|
self.trades.insert(*receiver, Arc::new(Mutex::new(state)));
|
|
}
|
|
|
|
pub fn in_trade(&self, client: &ClientId) -> bool {
|
|
self.trades.contains_key(client)
|
|
}
|
|
|
|
/*
|
|
pub async fn with<'a, T, F, Fut> (&'a self, client: &ClientId, func: F) -> Result<T, TradeStateError>
|
|
where
|
|
F: FnOnce(MutexGuard<'a, ClientTradeState>, MutexGuard<'a, ClientTradeState>) -> Fut + 'a,
|
|
Fut: Future<Output=T>
|
|
{
|
|
let c1 = self.trades.get(client).ok_or(TradeStateError::ClientNotInTrade(*client))?.lock().await;
|
|
let c2 = self.trades.get(&c1.other_client).ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?.lock().await;
|
|
|
|
// sanity check
|
|
if c1.client != c2.other_client {
|
|
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
|
|
}
|
|
Ok(func(c1, c2).await)
|
|
}
|
|
*/
|
|
pub async fn with<'a, T, F, Fut> (&'a self, client: &ClientId, func: F) -> Result<T, TradeStateError>
|
|
where
|
|
T: Send,
|
|
//F: for<'b> FnOnce(&'b mut ClientTradeState, &'b mut ClientTradeState) -> BoxFuture<'b, T> + Send + 'a
|
|
//F: for<'b> FnOnce(&'b mut ClientTradeState, &'b mut ClientTradeState) -> Fut + Send + 'a,
|
|
F: FnOnce(MutexGuard<'a, ClientTradeState>, MutexGuard<'a, ClientTradeState>) -> Fut + 'a,
|
|
Fut: Future<Output = T>,
|
|
{
|
|
let c1 = self.trades
|
|
.get(client)
|
|
.ok_or(TradeStateError::ClientNotInTrade(*client))?
|
|
.lock()
|
|
.await;
|
|
let c2 = self.trades
|
|
.get(&c1.other_client)
|
|
.ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?
|
|
.lock()
|
|
.await;
|
|
|
|
if c1.client != c2.other_client {
|
|
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
|
|
}
|
|
|
|
Ok(func(c1, c2).await)
|
|
}
|
|
|
|
// TODO: is it possible for this to not return Options?
|
|
pub async fn remove_trade(&mut self, client: &ClientId) -> (Option<ClientTradeState>, Option<ClientTradeState>) {
|
|
let c1 = OptionFuture::from(self.trades.remove(client).map(|c| async move {c.lock().await.clone()} )).await;
|
|
let c2 = if let Some(ref state) = c1 {
|
|
OptionFuture::from(self.trades.remove(&state.other_client).map(|c| async move {c.lock().await.clone()})).await
|
|
}
|
|
else {
|
|
None
|
|
};
|
|
|
|
(c1, c2)
|
|
}
|
|
}
|