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.

133 lines
3.5 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. use std::collections::HashMap;
  2. use std::cell::RefCell;
  3. use crate::common::serverstate::ClientId;
  4. use crate::ship::items;
  5. #[derive(Debug, Clone)]
  6. pub enum TradeItem {
  7. Individual(items::ClientItemId),
  8. Stacked(items::ClientItemId, usize),
  9. }
  10. impl TradeItem {
  11. pub fn stacked(&self) -> Option<(items::ClientItemId, usize)> {
  12. match self {
  13. TradeItem::Stacked(item_id, amount) => Some((*item_id, *amount)),
  14. _ => None
  15. }
  16. }
  17. pub fn stacked_mut(&mut self) -> Option<(items::ClientItemId, &mut usize)> {
  18. match self {
  19. TradeItem::Stacked(item_id, ref mut amount) => Some((*item_id, amount)),
  20. _ => None
  21. }
  22. }
  23. pub fn item_id(&self) -> items::ClientItemId {
  24. match self {
  25. TradeItem::Individual(item_id) => *item_id,
  26. TradeItem::Stacked(item_id, _) => *item_id,
  27. }
  28. }
  29. }
  30. #[derive(Debug, Clone, Eq, PartialEq)]
  31. pub enum TradeStatus {
  32. SentRequest,
  33. ReceivedRequest,
  34. Trading,
  35. Confirmed,
  36. FinalConfirm,
  37. ItemsChecked,
  38. TradeComplete,
  39. }
  40. #[derive(Debug, Clone)]
  41. pub struct ClientTradeState {
  42. client: ClientId,
  43. other_client: ClientId,
  44. pub items: Vec<TradeItem>,
  45. pub meseta: usize,
  46. pub status: TradeStatus,
  47. }
  48. impl ClientTradeState {
  49. pub fn client(&self) -> ClientId {
  50. self.client
  51. }
  52. pub fn other_client(&self) -> ClientId {
  53. self.other_client
  54. }
  55. }
  56. #[derive(thiserror::Error, Debug)]
  57. #[error("")]
  58. pub enum TradeStateError {
  59. ClientNotInTrade(ClientId),
  60. MismatchedTrade(ClientId, ClientId),
  61. }
  62. #[derive(Default, Debug)]
  63. pub struct TradeState {
  64. trades: HashMap<ClientId, RefCell<ClientTradeState>>,
  65. }
  66. impl TradeState {
  67. pub fn new_trade(&mut self, sender: &ClientId, receiver: &ClientId) {
  68. let state = ClientTradeState {
  69. client: *sender,
  70. other_client: *receiver,
  71. items: Default::default(),
  72. meseta: 0,
  73. status: TradeStatus::SentRequest,
  74. };
  75. self.trades.insert(*sender, RefCell::new(state));
  76. let state = ClientTradeState {
  77. client: *receiver,
  78. other_client: *sender,
  79. items: Default::default(),
  80. meseta: 0,
  81. status: TradeStatus::ReceivedRequest,
  82. };
  83. self.trades.insert(*receiver, RefCell::new(state));
  84. }
  85. pub fn in_trade(&self, client: &ClientId) -> bool {
  86. self.trades.contains_key(client)
  87. }
  88. pub fn with<T, F> (&self, client: &ClientId, func: F) -> Result<T, TradeStateError>
  89. where
  90. F: Fn(&mut ClientTradeState, &mut ClientTradeState) -> T
  91. {
  92. let mut c1 = self.trades.get(client).ok_or(TradeStateError::ClientNotInTrade(*client))?.borrow_mut();
  93. let mut c2 = self.trades.get(&c1.other_client).ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut();
  94. // sanity check
  95. if c1.client != c2.other_client {
  96. return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
  97. }
  98. Ok(func(&mut *c1, &mut *c2))
  99. }
  100. // TODO: is it possible for this to not return Options?
  101. pub fn remove_trade(&mut self, client: &ClientId) -> (Option<ClientTradeState>, Option<ClientTradeState>) {
  102. let c1 = self.trades.remove(client).map(|c| c.into_inner());
  103. let c2 = if let Some(ref state) = c1 {
  104. self.trades.remove(&state.other_client).map(|c| c.into_inner())
  105. }
  106. else {
  107. None
  108. };
  109. (c1, c2)
  110. }
  111. }