2021-12-10 13:24:59 -07:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::cell::RefCell;
|
|
|
|
use async_std::sync::{Arc, Mutex};
|
|
|
|
|
|
|
|
use crate::common::serverstate::ClientId;
|
|
|
|
use crate::ship::items;
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum TradeItem {
|
|
|
|
Individual(items::ClientItemId),
|
|
|
|
Stacked(items::ClientItemId, usize),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TradeItem {
|
|
|
|
pub fn stacked(&self) -> Option<(items::ClientItemId, usize)> {
|
|
|
|
match self {
|
|
|
|
TradeItem::Stacked(item_id, amount) => Some((*item_id, *amount as usize)),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn item_id(&self) -> items::ClientItemId {
|
|
|
|
match self {
|
|
|
|
TradeItem::Individual(item_id) => *item_id,
|
|
|
|
TradeItem::Stacked(item_id, _) => *item_id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[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>,
|
2021-12-12 22:55:08 -07:00
|
|
|
pub meseta: usize,
|
2021-12-10 13:24:59 -07:00
|
|
|
pub status: TradeStatus,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ClientTradeState {
|
|
|
|
pub fn client(&self) -> ClientId {
|
|
|
|
self.client
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn other_client(&self) -> ClientId {
|
|
|
|
self.other_client
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
pub struct ClientTradeHandle<'a> {
|
|
|
|
handle: std::cell::Ref<'a, ClientTradeState>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ClientTradeHandle<'a> {
|
|
|
|
fn new(handle: std::cell::Ref<'a, ClientTradeState>) -> ClientTradeHandle<'a> {
|
|
|
|
ClientTradeHandle {
|
|
|
|
handle: handle,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> std::ops::Deref for ClientTradeHandle<'a> {
|
|
|
|
type Target = ClientTradeState;
|
|
|
|
fn deref(&self) -> &ClientTradeState {
|
|
|
|
&self.handle
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> std::ops::DerefMut for ClientTradeHandle<'a> {
|
|
|
|
fn deref_mut(&mut self) -> &mut ClientTradeState {
|
|
|
|
&mut self.handle
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Clone for ClientTradeHandle<'a> {
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
|
|
#[error("")]
|
|
|
|
pub enum TradeStateError {
|
|
|
|
ClientNotInTrade(ClientId),
|
|
|
|
MismatchedTrade(ClientId, ClientId),
|
|
|
|
}
|
|
|
|
|
2021-12-10 23:41:17 -07:00
|
|
|
#[derive(Default, Debug)]
|
2021-12-10 13:24:59 -07:00
|
|
|
pub struct TradeState {
|
|
|
|
trades: HashMap<ClientId, RefCell<ClientTradeState>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TradeState {
|
|
|
|
pub fn new_trade(&mut self, sender: &ClientId, receiver: &ClientId) {
|
|
|
|
let state = ClientTradeState {
|
|
|
|
client: *sender,
|
|
|
|
other_client: *receiver,
|
|
|
|
items: Default::default(),
|
2021-12-12 22:55:08 -07:00
|
|
|
meseta: 0,
|
2021-12-10 13:24:59 -07:00
|
|
|
status: TradeStatus::SentRequest,
|
|
|
|
};
|
|
|
|
self.trades.insert(*sender, RefCell::new(state));
|
|
|
|
|
|
|
|
let state = ClientTradeState {
|
|
|
|
client: *receiver,
|
|
|
|
other_client: *sender,
|
|
|
|
items: Default::default(),
|
2021-12-12 22:55:08 -07:00
|
|
|
meseta: 0,
|
2021-12-10 13:24:59 -07:00
|
|
|
status: TradeStatus::ReceivedRequest,
|
|
|
|
};
|
|
|
|
self.trades.insert(*receiver, RefCell::new(state));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with<T, F> (&self, client: &ClientId, func: F) -> Result<T, TradeStateError>
|
|
|
|
where
|
|
|
|
F: Fn(&mut ClientTradeState, &mut ClientTradeState) -> T
|
|
|
|
{
|
|
|
|
let mut c1 = self.trades.get(client).ok_or_else(|| TradeStateError::ClientNotInTrade(*client))?.borrow_mut();
|
|
|
|
let mut c2 = self.trades.get(&c1.other_client).ok_or_else(|| TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut();
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
if c1.client != c2.other_client {
|
|
|
|
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(func(&mut *c1, &mut *c2))
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
pub fn with<T, F> (&self, client: &ClientId, func: F) -> Result<T, TradeStateError>
|
|
|
|
where
|
|
|
|
F: Fn(&mut ClientTradeHandle, &mut ClientTradeHandle) -> T
|
|
|
|
{
|
|
|
|
let c1 = ClientTradeHandle::new(self.trades.get(client).ok_or_else(|| TradeStateError::ClientNotInTrade(*client))?.borrow_mut());
|
|
|
|
let c2 = ClientTradeHandle::new(self.trades.get(&c1.other_client).ok_or_else(|| TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut());
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
if c1.client != c2.other_client {
|
|
|
|
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(func(&mut c1, &mut c2))
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// TODO: is it possible for this to not return Options?
|
|
|
|
pub fn remove_trade(&mut self, client: &ClientId) -> (Option<ClientTradeState>, Option<ClientTradeState>) {
|
|
|
|
let c1 = self.trades.remove(client).map(|c| c.into_inner());
|
|
|
|
let c2 = if let Some(ref state) = c1 {
|
|
|
|
self.trades.remove(&state.other_client).map(|c| c.into_inner())
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
(c1, c2)
|
|
|
|
}
|
|
|
|
}
|