elseware/src/ship/trade.rs

183 lines
4.8 KiB
Rust
Raw Normal View History

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)),
2021-12-10 13:24:59 -07:00
_ => None
}
}
pub fn stacked_mut(&mut self) -> Option<(items::ClientItemId, &mut usize)> {
match self {
TradeItem::Stacked(item_id, ref mut amount) => Some((*item_id, amount)),
_ => None
}
}
pub fn item_id(&self) -> items::ClientItemId {
2021-12-10 13:24:59 -07:00
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 in_trade(&self, client: &ClientId) -> bool {
self.trades.contains_key(client)
}
2021-12-10 13:24:59 -07:00
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)
}
}