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.

3957 lines
157 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. use std::convert::TryInto;
  2. use networking::serverstate::{ClientId, ServerState};
  3. use entity::gateway::{EntityGateway, InMemoryGateway};
  4. use entity::item;
  5. use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
  6. use entity::item::{Meseta, ItemEntity, InventoryItemEntity};
  7. use elseware::ship::packet::handler::trade::TradeError;
  8. use libpso::packet::ship::*;
  9. use libpso::packet::messages::*;
  10. #[path = "common.rs"]
  11. mod common;
  12. use common::*;
  13. async fn initialize_trade<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) {
  14. ship.handle(client1, RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
  15. client: client1.0 as u8 -1,
  16. target: 0,
  17. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
  18. })))).await.unwrap();
  19. ship.handle(client2, RecvShipPacket::DirectMessage(DirectMessage::new(client1.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
  20. client: client2.0 as u8 -1,
  21. target: 0,
  22. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Respond, 0)
  23. })))).await.unwrap();
  24. }
  25. async fn confirm_trade<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) {
  26. ship.handle(client1, RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
  27. client: client1.0 as u8 -1,
  28. target: 0,
  29. trade: TradeRequestCommand::Confirm
  30. })))).await.unwrap();
  31. ship.handle(client2, RecvShipPacket::DirectMessage(DirectMessage::new(client1.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
  32. client: client2.0 as u8 -1,
  33. target: 0,
  34. trade: TradeRequestCommand::Confirm
  35. })))).await.unwrap();
  36. }
  37. async fn finalconfirm_trade<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) {
  38. ship.handle(client1, RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
  39. client: client1.0 as u8 -1,
  40. target: 0,
  41. trade: TradeRequestCommand::FinalConfirm
  42. })))).await.unwrap();
  43. ship.handle(client2, RecvShipPacket::DirectMessage(DirectMessage::new(client1.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
  44. client: client2.0 as u8 -1,
  45. target: 0,
  46. trade: TradeRequestCommand::FinalConfirm
  47. })))).await.unwrap();
  48. }
  49. #[derive(Default)]
  50. struct TradeItemBuilder {
  51. count: usize,
  52. items: [TradeItem; 32],
  53. }
  54. impl TradeItemBuilder {
  55. fn individual(mut self, item: &InventoryItemEntity, item_id: u32) -> Self {
  56. let idata = item.with_individual(|i| i.item.as_client_bytes()).unwrap();
  57. self.items[self.count] = TradeItem {
  58. item_data: idata[0..12].try_into().unwrap(),
  59. item_id: item_id,
  60. item_data2: idata[12..16].try_into().unwrap(),
  61. };
  62. self.count += 1;
  63. self
  64. }
  65. fn stacked(mut self, item: &InventoryItemEntity, item_id: u32, amount: u8) -> Self {
  66. let idata = item
  67. .with_stacked(|i| i[0].item.tool().unwrap().as_stacked_bytes(i.len()))
  68. .map(|mut data| {
  69. data[5] = amount;
  70. data
  71. })
  72. .unwrap();
  73. self.items[self.count] = TradeItem {
  74. item_data: idata[0..12].try_into().unwrap(),
  75. item_id: item_id,
  76. item_data2: idata[12..16].try_into().unwrap(),
  77. };
  78. self.count += 1;
  79. self
  80. }
  81. fn meseta(mut self, amount: usize) -> Self {
  82. self.items[self.count] = TradeItem {
  83. item_data: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  84. item_id: 0xFFFFFFFF,
  85. item_data2: u32::to_le_bytes(amount as u32),
  86. };
  87. self.count += 1;
  88. self
  89. }
  90. fn build(self) -> [TradeItem; 32] {
  91. self.items
  92. }
  93. }
  94. #[async_std::test]
  95. async fn test_trade_one_individual_item() {
  96. let mut entity_gateway = InMemoryGateway::default();
  97. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  98. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  99. let mut p1_inv = Vec::new();
  100. p1_inv.push(entity_gateway.create_item(
  101. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  102. .as_new()
  103. ).await.unwrap());
  104. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  105. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  106. let mut ship = standard_ship(entity_gateway.clone());
  107. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  108. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  109. join_lobby(&mut ship, ClientId(1)).await;
  110. join_lobby(&mut ship, ClientId(2)).await;
  111. create_room(&mut ship, ClientId(1), "room", "").await;
  112. join_room(&mut ship, ClientId(2), 0).await;
  113. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  114. assert_eq!(p1_items.items.len(), 1);
  115. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  116. assert_eq!(p2_items.items.len(), 0);
  117. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  118. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  119. client: 1,
  120. target: 0,
  121. trade: TradeRequestCommand::AddItem(0x10000, 1)
  122. })))).await.unwrap();
  123. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  124. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  125. let titems = TradeItemBuilder::default()
  126. .individual(&p1_items.items[0], 0x10000)
  127. .build();
  128. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  129. trade_target: 1,
  130. unknown2: 0,
  131. count: 1,
  132. items: titems,
  133. })).await.unwrap();
  134. assert_eq!(ack.len(), 0);
  135. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  136. trade_target: 0,
  137. unknown2: 0,
  138. count: 0,
  139. items: Default::default(),
  140. })).await.unwrap();
  141. assert_eq!(ack.len(), 2);
  142. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  143. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  144. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  145. })).await.unwrap();
  146. assert_eq!(ack.len(), 0);
  147. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  148. })).await.unwrap();
  149. assert_eq!(ack.len(), 5);
  150. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  151. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  152. ..
  153. }))));
  154. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  155. msg: GameMessage::CreateItem(CreateItem {..}),
  156. ..
  157. }))));
  158. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  159. msg: GameMessage::CreateItem(CreateItem {..}),
  160. ..
  161. }))));
  162. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  163. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  164. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  165. assert_eq!(p1_items.items.len(), 0);
  166. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  167. assert_eq!(p2_items.items.len(), 1);
  168. }
  169. #[async_std::test]
  170. async fn test_trade_player2_to_player1() {
  171. let mut entity_gateway = InMemoryGateway::default();
  172. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  173. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  174. let mut p2_inv = Vec::new();
  175. p2_inv.push(entity_gateway.create_item(
  176. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  177. .as_new()
  178. ).await.unwrap());
  179. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  180. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  181. let mut ship = standard_ship(entity_gateway.clone());
  182. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  183. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  184. join_lobby(&mut ship, ClientId(1)).await;
  185. join_lobby(&mut ship, ClientId(2)).await;
  186. create_room(&mut ship, ClientId(1), "room", "").await;
  187. join_room(&mut ship, ClientId(2), 0).await;
  188. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  189. assert_eq!(p1_items.items.len(), 0);
  190. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  191. assert_eq!(p2_items.items.len(), 1);
  192. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  193. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  194. client: 1,
  195. target: 0,
  196. trade: TradeRequestCommand::AddItem(0x210000, 1)
  197. })))).await.unwrap();
  198. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  199. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  200. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  201. trade_target: 1,
  202. unknown2: 0,
  203. count: 0,
  204. items: Default::default(),
  205. })).await.unwrap();
  206. assert_eq!(ack.len(), 0);
  207. let titems = TradeItemBuilder::default()
  208. .individual(&p2_items.items[0], 0x210000)
  209. .build();
  210. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  211. trade_target: 0,
  212. unknown2: 0,
  213. count: 1,
  214. items: titems,
  215. })).await.unwrap();
  216. assert_eq!(ack.len(), 2);
  217. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  218. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  219. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  220. })).await.unwrap();
  221. assert_eq!(ack.len(), 0);
  222. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  223. })).await.unwrap();
  224. assert_eq!(ack.len(), 5);
  225. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  226. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  227. ..
  228. }))));
  229. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  230. msg: GameMessage::CreateItem(CreateItem {..}),
  231. ..
  232. }))));
  233. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  234. msg: GameMessage::CreateItem(CreateItem {..}),
  235. ..
  236. }))));
  237. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  238. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  239. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  240. assert_eq!(p1_items.items.len(), 1);
  241. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  242. assert_eq!(p2_items.items.len(), 0);
  243. }
  244. #[async_std::test]
  245. async fn test_reverse_trade_ack_order() {
  246. let mut entity_gateway = InMemoryGateway::default();
  247. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  248. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  249. let mut p1_inv = Vec::new();
  250. p1_inv.push(entity_gateway.create_item(
  251. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  252. .as_new()
  253. ).await.unwrap());
  254. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  255. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  256. let mut ship = standard_ship(entity_gateway.clone());
  257. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  258. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  259. join_lobby(&mut ship, ClientId(1)).await;
  260. join_lobby(&mut ship, ClientId(2)).await;
  261. create_room(&mut ship, ClientId(1), "room", "").await;
  262. join_room(&mut ship, ClientId(2), 0).await;
  263. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  264. assert_eq!(p1_items.items.len(), 1);
  265. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  266. assert_eq!(p2_items.items.len(), 0);
  267. initialize_trade(&mut ship, ClientId(2), ClientId(1)).await;
  268. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  269. client: 1,
  270. target: 0,
  271. trade: TradeRequestCommand::AddItem(0x10000, 1)
  272. })))).await.unwrap();
  273. confirm_trade(&mut ship, ClientId(2), ClientId(1)).await;
  274. finalconfirm_trade(&mut ship, ClientId(2), ClientId(1)).await;
  275. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  276. trade_target: 0,
  277. unknown2: 0,
  278. count: 0,
  279. items: Default::default(),
  280. })).await.unwrap();
  281. assert_eq!(ack.len(), 0);
  282. let titems = TradeItemBuilder::default()
  283. .individual(&p1_items.items[0], 0x10000)
  284. .build();
  285. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  286. trade_target: 1,
  287. unknown2: 0,
  288. count: 1,
  289. items: titems,
  290. })).await.unwrap();
  291. assert_eq!(ack.len(), 2);
  292. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  293. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  294. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  295. })).await.unwrap();
  296. assert_eq!(ack.len(), 0);
  297. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  298. })).await.unwrap();
  299. assert_eq!(ack.len(), 5);
  300. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  301. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  302. ..
  303. }))));
  304. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  305. msg: GameMessage::CreateItem(CreateItem {..}),
  306. ..
  307. }))));
  308. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  309. msg: GameMessage::CreateItem(CreateItem {..}),
  310. ..
  311. }))));
  312. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  313. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  314. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  315. assert_eq!(p1_items.items.len(), 0);
  316. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  317. assert_eq!(p2_items.items.len(), 1);
  318. }
  319. #[async_std::test]
  320. async fn test_trade_one_stacked_item() {
  321. let mut entity_gateway = InMemoryGateway::default();
  322. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  323. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  324. let p1_stack = futures::future::join_all((0..2).map(|_| {
  325. let mut entity_gateway = entity_gateway.clone();
  326. async move {
  327. entity_gateway.create_item(
  328. ItemBuilder::tool(item::tool::ToolType::Monomate)
  329. .as_new()
  330. ).await
  331. }}))
  332. .await
  333. .into_iter()
  334. .collect::<Result<Vec<ItemEntity>,_>>()
  335. .unwrap();
  336. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  337. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  338. let mut ship = standard_ship(entity_gateway.clone());
  339. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  340. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  341. join_lobby(&mut ship, ClientId(1)).await;
  342. join_lobby(&mut ship, ClientId(2)).await;
  343. create_room(&mut ship, ClientId(1), "room", "").await;
  344. join_room(&mut ship, ClientId(2), 0).await;
  345. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  346. assert_eq!(p1_items.items.len(), 1);
  347. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  348. assert_eq!(p2_items.items.len(), 0);
  349. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  350. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  351. client: 1,
  352. target: 0,
  353. trade: TradeRequestCommand::AddItem(0x10000, 2)
  354. })))).await.unwrap();
  355. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  356. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  357. let titems = TradeItemBuilder::default()
  358. .stacked(&p1_items.items[0], 0x10000, 2)
  359. .build();
  360. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  361. trade_target: 1,
  362. unknown2: 0,
  363. count: 1,
  364. items: titems,
  365. })).await.unwrap();
  366. assert_eq!(ack.len(), 0);
  367. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  368. trade_target: 0,
  369. unknown2: 0,
  370. count: 0,
  371. items: Default::default(),
  372. })).await.unwrap();
  373. assert_eq!(ack.len(), 2);
  374. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  375. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  376. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  377. })).await.unwrap();
  378. assert_eq!(ack.len(), 0);
  379. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  380. })).await.unwrap();
  381. assert_eq!(ack.len(), 5);
  382. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  383. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  384. ..
  385. }))));
  386. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  387. msg: GameMessage::CreateItem(CreateItem {..}),
  388. ..
  389. }))));
  390. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  391. msg: GameMessage::CreateItem(CreateItem {..}),
  392. ..
  393. }))));
  394. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  395. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  396. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  397. assert_eq!(p1_items.items.len(), 0);
  398. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  399. assert_eq!(p2_items.items.len(), 1);
  400. }
  401. #[async_std::test]
  402. async fn test_trade_partial_stacked_item() {
  403. let mut entity_gateway = InMemoryGateway::default();
  404. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  405. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  406. let p1_stack = futures::future::join_all((0..2).map(|_| {
  407. let mut entity_gateway = entity_gateway.clone();
  408. async move {
  409. entity_gateway.create_item(
  410. ItemBuilder::tool(item::tool::ToolType::Monomate)
  411. .as_new()
  412. ).await
  413. }}))
  414. .await
  415. .into_iter()
  416. .collect::<Result<Vec<ItemEntity>,_>>()
  417. .unwrap();
  418. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  419. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  420. let mut ship = standard_ship(entity_gateway.clone());
  421. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  422. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  423. join_lobby(&mut ship, ClientId(1)).await;
  424. join_lobby(&mut ship, ClientId(2)).await;
  425. create_room(&mut ship, ClientId(1), "room", "").await;
  426. join_room(&mut ship, ClientId(2), 0).await;
  427. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  428. assert_eq!(p1_items.items.len(), 1);
  429. assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 2);
  430. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  431. assert_eq!(p2_items.items.len(), 0);
  432. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  433. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  434. client: 1,
  435. target: 0,
  436. trade: TradeRequestCommand::AddItem(0x10000, 1)
  437. })))).await.unwrap();
  438. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  439. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  440. let titems = TradeItemBuilder::default()
  441. .stacked(&p1_items.items[0], 0x10000, 1)
  442. .build();
  443. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  444. trade_target: 1,
  445. unknown2: 0,
  446. count: 1,
  447. items: titems,
  448. })).await.unwrap();
  449. assert_eq!(ack.len(), 0);
  450. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  451. trade_target: 0,
  452. unknown2: 0,
  453. count: 0,
  454. items: Default::default(),
  455. })).await.unwrap();
  456. assert_eq!(ack.len(), 2);
  457. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  458. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  459. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  460. })).await.unwrap();
  461. assert_eq!(ack.len(), 0);
  462. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  463. })).await.unwrap();
  464. assert_eq!(ack.len(), 5);
  465. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  466. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  467. ..
  468. }))));
  469. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  470. msg: GameMessage::CreateItem(CreateItem {..}),
  471. ..
  472. }))));
  473. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  474. msg: GameMessage::CreateItem(CreateItem {..}),
  475. ..
  476. }))));
  477. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  478. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  479. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  480. assert_eq!(p1_items.items.len(), 1);
  481. assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 1);
  482. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  483. assert_eq!(p2_items.items.len(), 1);
  484. assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 1);
  485. }
  486. #[async_std::test]
  487. async fn test_trade_individual_both() {
  488. let mut entity_gateway = InMemoryGateway::default();
  489. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  490. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  491. let p1_inv = vec![
  492. entity_gateway.create_item(
  493. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  494. .as_new()
  495. ).await.unwrap()];
  496. let p2_inv = vec![
  497. entity_gateway.create_item(
  498. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  499. .as_new()
  500. ).await.unwrap()];
  501. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  502. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  503. let mut ship = standard_ship(entity_gateway.clone());
  504. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  505. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  506. join_lobby(&mut ship, ClientId(1)).await;
  507. join_lobby(&mut ship, ClientId(2)).await;
  508. create_room(&mut ship, ClientId(1), "room", "").await;
  509. join_room(&mut ship, ClientId(2), 0).await;
  510. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  511. assert_eq!(p1_items.items.len(), 1);
  512. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  513. assert_eq!(p2_items.items.len(), 1);
  514. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  515. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  516. client: 1,
  517. target: 0,
  518. trade: TradeRequestCommand::AddItem(0x10000, 1)
  519. })))).await.unwrap();
  520. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  521. client: 0,
  522. target: 0,
  523. trade: TradeRequestCommand::AddItem(0x210000, 1)
  524. })))).await.unwrap();
  525. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  526. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  527. let titems = TradeItemBuilder::default()
  528. .individual(&p1_items.items[0], 0x10000)
  529. .build();
  530. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  531. trade_target: 1,
  532. unknown2: 0,
  533. count: 1,
  534. items: titems,
  535. })).await.unwrap();
  536. assert_eq!(ack.len(), 0);
  537. let titems = TradeItemBuilder::default()
  538. .individual(&p2_items.items[0], 0x210000)
  539. .build();
  540. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  541. trade_target: 0,
  542. unknown2: 0,
  543. count: 1,
  544. items: titems,
  545. })).await.unwrap();
  546. assert_eq!(ack.len(), 2);
  547. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  548. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  549. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  550. })).await.unwrap();
  551. assert_eq!(ack.len(), 0);
  552. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  553. })).await.unwrap();
  554. assert_eq!(ack.len(), 8);
  555. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  556. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  557. client: 1,
  558. item_id: 0x210000,
  559. ..
  560. }),
  561. ..
  562. }))));
  563. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  564. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  565. client: 0,
  566. item_id: 0x10000,
  567. ..
  568. }),
  569. ..
  570. }))));
  571. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  572. msg: GameMessage::CreateItem(CreateItem {
  573. client: 1,
  574. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  575. item_id: 0x810002,
  576. ..
  577. }),
  578. ..
  579. }))));
  580. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  581. msg: GameMessage::CreateItem(CreateItem {
  582. client: 1,
  583. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  584. item_id: 0x810002,
  585. ..
  586. }),
  587. ..
  588. }))));
  589. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  590. msg: GameMessage::CreateItem(CreateItem {
  591. client: 0,
  592. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  593. item_id: 0x810001,
  594. ..
  595. }),
  596. ..
  597. }))));
  598. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  599. msg: GameMessage::CreateItem(CreateItem {
  600. client: 0,
  601. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  602. item_id: 0x810001,
  603. ..
  604. }),
  605. ..
  606. }))));
  607. assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  608. assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  609. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  610. assert_eq!(p1_items.items.len(), 1);
  611. assert!(matches!(p1_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Handgun, ..}), ..}));
  612. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  613. assert_eq!(p2_items.items.len(), 1);
  614. assert!(matches!(p2_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Saber, ..}), ..}));
  615. }
  616. #[async_std::test]
  617. async fn test_trade_stacked_both() {
  618. let mut entity_gateway = InMemoryGateway::default();
  619. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  620. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  621. let p1_stack = futures::future::join_all((0..2).map(|_| {
  622. let mut entity_gateway = entity_gateway.clone();
  623. async move {
  624. entity_gateway.create_item(
  625. ItemBuilder::tool(item::tool::ToolType::Monomate)
  626. .as_new()
  627. ).await
  628. }}))
  629. .await
  630. .into_iter()
  631. .collect::<Result<Vec<ItemEntity>,_>>()
  632. .unwrap();
  633. let p2_stack = futures::future::join_all((0..3).map(|_| {
  634. let mut entity_gateway = entity_gateway.clone();
  635. async move {
  636. entity_gateway.create_item(
  637. ItemBuilder::tool(item::tool::ToolType::Monofluid)
  638. .as_new()
  639. ).await
  640. }}))
  641. .await
  642. .into_iter()
  643. .collect::<Result<Vec<ItemEntity>,_>>()
  644. .unwrap();
  645. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  646. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  647. let mut ship = standard_ship(entity_gateway.clone());
  648. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  649. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  650. join_lobby(&mut ship, ClientId(1)).await;
  651. join_lobby(&mut ship, ClientId(2)).await;
  652. create_room(&mut ship, ClientId(1), "room", "").await;
  653. join_room(&mut ship, ClientId(2), 0).await;
  654. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  655. assert_eq!(p1_items.items.len(), 1);
  656. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  657. assert_eq!(p2_items.items.len(), 1);
  658. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  659. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  660. client: 1,
  661. target: 0,
  662. trade: TradeRequestCommand::AddItem(0x10000, 2)
  663. })))).await.unwrap();
  664. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  665. client: 0,
  666. target: 0,
  667. trade: TradeRequestCommand::AddItem(0x210000, 3)
  668. })))).await.unwrap();
  669. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  670. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  671. let titems = TradeItemBuilder::default()
  672. .stacked(&p1_items.items[0], 0x10000, 2)
  673. .build();
  674. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  675. trade_target: 1,
  676. unknown2: 0,
  677. count: 1,
  678. items: titems,
  679. })).await.unwrap();
  680. assert_eq!(ack.len(), 0);
  681. let titems = TradeItemBuilder::default()
  682. .stacked(&p2_items.items[0], 0x210000, 3)
  683. .build();
  684. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  685. trade_target: 0,
  686. unknown2: 0,
  687. count: 1,
  688. items: titems,
  689. })).await.unwrap();
  690. assert_eq!(ack.len(), 2);
  691. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  692. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  693. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  694. })).await.unwrap();
  695. assert_eq!(ack.len(), 0);
  696. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  697. })).await.unwrap();
  698. assert_eq!(ack.len(), 8);
  699. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  700. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  701. client: 1,
  702. item_id: 0x210000,
  703. ..
  704. }),
  705. ..
  706. }))));
  707. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  708. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  709. client: 0,
  710. item_id: 0x10000,
  711. ..
  712. }),
  713. ..
  714. }))));
  715. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  716. msg: GameMessage::CreateItem(CreateItem {
  717. client: 1,
  718. item_id: 0x810002,
  719. ..
  720. }),
  721. ..
  722. }))));
  723. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  724. msg: GameMessage::CreateItem(CreateItem {
  725. client: 1,
  726. item_id: 0x810002,
  727. ..
  728. }),
  729. ..
  730. }))));
  731. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  732. msg: GameMessage::CreateItem(CreateItem {
  733. client: 0,
  734. item_id: 0x810001,
  735. ..
  736. }),
  737. ..
  738. }))));
  739. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  740. msg: GameMessage::CreateItem(CreateItem {
  741. client: 0,
  742. item_id: 0x810001,
  743. ..
  744. }),
  745. ..
  746. }))));
  747. assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  748. assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  749. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  750. assert_eq!(p1_items.items.len(), 1);
  751. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 3);
  752. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
  753. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  754. assert_eq!(p2_items.items.len(), 1);
  755. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  756. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  757. }
  758. #[async_std::test]
  759. async fn test_trade_partial_stack_both() {
  760. let mut entity_gateway = InMemoryGateway::default();
  761. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  762. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  763. let p1_stack = futures::future::join_all((0..2).map(|_| {
  764. let mut entity_gateway = entity_gateway.clone();
  765. async move {
  766. entity_gateway.create_item(
  767. ItemBuilder::tool(item::tool::ToolType::Monomate)
  768. .as_new()
  769. ).await
  770. }}))
  771. .await
  772. .into_iter()
  773. .collect::<Result<Vec<ItemEntity>,_>>()
  774. .unwrap();
  775. let p2_stack = futures::future::join_all((0..3).map(|_| {
  776. let mut entity_gateway = entity_gateway.clone();
  777. async move {
  778. entity_gateway.create_item(
  779. ItemBuilder::tool(item::tool::ToolType::Monofluid)
  780. .as_new()
  781. ).await
  782. }}))
  783. .await
  784. .into_iter()
  785. .collect::<Result<Vec<ItemEntity>,_>>()
  786. .unwrap();
  787. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  788. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  789. let mut ship = standard_ship(entity_gateway.clone());
  790. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  791. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  792. join_lobby(&mut ship, ClientId(1)).await;
  793. join_lobby(&mut ship, ClientId(2)).await;
  794. create_room(&mut ship, ClientId(1), "room", "").await;
  795. join_room(&mut ship, ClientId(2), 0).await;
  796. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  797. assert_eq!(p1_items.items.len(), 1);
  798. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  799. assert_eq!(p2_items.items.len(), 1);
  800. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  801. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  802. client: 1,
  803. target: 0,
  804. trade: TradeRequestCommand::AddItem(0x10000, 1)
  805. })))).await.unwrap();
  806. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  807. client: 0,
  808. target: 0,
  809. trade: TradeRequestCommand::AddItem(0x210000, 2)
  810. })))).await.unwrap();
  811. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  812. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  813. let titems = TradeItemBuilder::default()
  814. .stacked(&p1_items.items[0], 0x10000, 1)
  815. .build();
  816. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  817. trade_target: 1,
  818. unknown2: 0,
  819. count: 1,
  820. items: titems,
  821. })).await.unwrap();
  822. assert_eq!(ack.len(), 0);
  823. let titems = TradeItemBuilder::default()
  824. .stacked(&p2_items.items[0], 0x210000, 2)
  825. .build();
  826. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  827. trade_target: 0,
  828. unknown2: 0,
  829. count: 1,
  830. items: titems,
  831. })).await.unwrap();
  832. assert_eq!(ack.len(), 2);
  833. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  834. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  835. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  836. })).await.unwrap();
  837. assert_eq!(ack.len(), 0);
  838. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  839. })).await.unwrap();
  840. assert_eq!(ack.len(), 8);
  841. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  842. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  843. client: 1,
  844. item_id: 0x210000,
  845. amount: 2,
  846. ..
  847. }),
  848. ..
  849. }))));
  850. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  851. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  852. client: 0,
  853. item_id: 0x10000,
  854. amount: 1,
  855. ..
  856. }),
  857. ..
  858. }))));
  859. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  860. msg: GameMessage::CreateItem(CreateItem {
  861. client: 1,
  862. item_id: 0x810002,
  863. ..
  864. }),
  865. ..
  866. }))));
  867. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  868. msg: GameMessage::CreateItem(CreateItem {
  869. client: 1,
  870. item_id: 0x810002,
  871. ..
  872. }),
  873. ..
  874. }))));
  875. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  876. msg: GameMessage::CreateItem(CreateItem {
  877. client: 0,
  878. item_id: 0x810001,
  879. ..
  880. }),
  881. ..
  882. }))));
  883. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  884. msg: GameMessage::CreateItem(CreateItem {
  885. client: 0,
  886. item_id: 0x810001,
  887. ..
  888. }),
  889. ..
  890. }))));
  891. assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  892. assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  893. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  894. assert_eq!(p1_items.items.len(), 2);
  895. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  896. assert_eq!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
  897. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  898. assert!(matches!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
  899. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  900. assert_eq!(p2_items.items.len(), 2);
  901. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  902. assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 1);
  903. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
  904. assert!(matches!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  905. }
  906. #[async_std::test]
  907. async fn test_trade_same_stacked_item_to_eachother() {
  908. let mut entity_gateway = InMemoryGateway::default();
  909. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  910. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  911. let p1_stack = futures::future::join_all((0..3).map(|_| {
  912. let mut entity_gateway = entity_gateway.clone();
  913. async move {
  914. entity_gateway.create_item(
  915. ItemBuilder::tool(item::tool::ToolType::Monomate)
  916. .as_new()
  917. ).await
  918. }}))
  919. .await
  920. .into_iter()
  921. .collect::<Result<Vec<ItemEntity>,_>>()
  922. .unwrap();
  923. let p2_stack = futures::future::join_all((0..4).map(|_| {
  924. let mut entity_gateway = entity_gateway.clone();
  925. async move {
  926. entity_gateway.create_item(
  927. ItemBuilder::tool(item::tool::ToolType::Monomate)
  928. .as_new()
  929. ).await
  930. }}))
  931. .await
  932. .into_iter()
  933. .collect::<Result<Vec<ItemEntity>,_>>()
  934. .unwrap();
  935. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  936. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  937. let mut ship = standard_ship(entity_gateway.clone());
  938. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  939. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  940. join_lobby(&mut ship, ClientId(1)).await;
  941. join_lobby(&mut ship, ClientId(2)).await;
  942. create_room(&mut ship, ClientId(1), "room", "").await;
  943. join_room(&mut ship, ClientId(2), 0).await;
  944. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  945. assert_eq!(p1_items.items.len(), 1);
  946. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  947. assert_eq!(p2_items.items.len(), 1);
  948. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  949. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  950. client: 1,
  951. target: 0,
  952. trade: TradeRequestCommand::AddItem(0x10000, 1)
  953. })))).await.unwrap();
  954. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  955. client: 0,
  956. target: 0,
  957. trade: TradeRequestCommand::AddItem(0x210000, 3)
  958. })))).await.unwrap();
  959. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  960. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  961. let titems = TradeItemBuilder::default()
  962. .stacked(&p1_items.items[0], 0x10000, 1)
  963. .build();
  964. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  965. trade_target: 1,
  966. unknown2: 0,
  967. count: 1,
  968. items: titems,
  969. })).await.unwrap();
  970. assert_eq!(ack.len(), 0);
  971. let titems = TradeItemBuilder::default()
  972. .stacked(&p2_items.items[0], 0x210000, 3)
  973. .build();
  974. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  975. trade_target: 0,
  976. unknown2: 0,
  977. count: 1,
  978. items: titems,
  979. })).await.unwrap();
  980. assert_eq!(ack.len(), 2);
  981. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  982. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  983. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  984. })).await.unwrap();
  985. assert_eq!(ack.len(), 0);
  986. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  987. })).await.unwrap();
  988. assert_eq!(ack.len(), 8);
  989. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  990. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  991. client: 1,
  992. item_id: 0x210000,
  993. amount: 3,
  994. ..
  995. }),
  996. ..
  997. }))));
  998. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  999. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1000. client: 0,
  1001. item_id: 0x10000,
  1002. amount: 1,
  1003. ..
  1004. }),
  1005. ..
  1006. }))));
  1007. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  1008. msg: GameMessage::CreateItem(CreateItem {
  1009. client: 1,
  1010. item_id: 0x810002,
  1011. ..
  1012. }),
  1013. ..
  1014. }))));
  1015. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1016. msg: GameMessage::CreateItem(CreateItem {
  1017. client: 1,
  1018. item_id: 0x810002,
  1019. ..
  1020. }),
  1021. ..
  1022. }))));
  1023. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1024. msg: GameMessage::CreateItem(CreateItem {
  1025. client: 0,
  1026. item_id: 0x810001,
  1027. ..
  1028. }),
  1029. ..
  1030. }))));
  1031. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1032. msg: GameMessage::CreateItem(CreateItem {
  1033. client: 0,
  1034. item_id: 0x810001,
  1035. ..
  1036. }),
  1037. ..
  1038. }))));
  1039. assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  1040. assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  1041. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1042. assert_eq!(p1_items.items.len(), 1);
  1043. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 5);
  1044. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  1045. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1046. assert_eq!(p2_items.items.len(), 1);
  1047. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  1048. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  1049. }
  1050. #[async_std::test]
  1051. async fn test_trade_stacked_when_already_have_partial_stack() {
  1052. let mut entity_gateway = InMemoryGateway::default();
  1053. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1054. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1055. let p1_stack = futures::future::join_all((0..3).map(|_| {
  1056. let mut entity_gateway = entity_gateway.clone();
  1057. async move {
  1058. entity_gateway.create_item(
  1059. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1060. .as_new()
  1061. ).await
  1062. }}))
  1063. .await
  1064. .into_iter()
  1065. .collect::<Result<Vec<ItemEntity>,_>>()
  1066. .unwrap();
  1067. let p2_stack = futures::future::join_all((0..3).map(|_| {
  1068. let mut entity_gateway = entity_gateway.clone();
  1069. async move {
  1070. entity_gateway.create_item(
  1071. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1072. .as_new()
  1073. ).await
  1074. }}))
  1075. .await
  1076. .into_iter()
  1077. .collect::<Result<Vec<ItemEntity>,_>>()
  1078. .unwrap();
  1079. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  1080. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  1081. let mut ship = standard_ship(entity_gateway.clone());
  1082. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1083. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1084. join_lobby(&mut ship, ClientId(1)).await;
  1085. join_lobby(&mut ship, ClientId(2)).await;
  1086. create_room(&mut ship, ClientId(1), "room", "").await;
  1087. join_room(&mut ship, ClientId(2), 0).await;
  1088. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1089. assert_eq!(p1_items.items.len(), 1);
  1090. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1091. assert_eq!(p2_items.items.len(), 1);
  1092. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1093. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1094. client: 1,
  1095. target: 0,
  1096. trade: TradeRequestCommand::AddItem(0x10000, 2)
  1097. })))).await.unwrap();
  1098. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1099. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1100. let titems = TradeItemBuilder::default()
  1101. .stacked(&p1_items.items[0], 0x10000, 2)
  1102. .build();
  1103. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1104. trade_target: 1,
  1105. unknown2: 0,
  1106. count: 1,
  1107. items: titems,
  1108. })).await.unwrap();
  1109. assert_eq!(ack.len(), 0);
  1110. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1111. trade_target: 0,
  1112. unknown2: 0,
  1113. count: 0,
  1114. items: Default::default(),
  1115. })).await.unwrap();
  1116. assert_eq!(ack.len(), 2);
  1117. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1118. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1119. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1120. })).await.unwrap();
  1121. assert_eq!(ack.len(), 0);
  1122. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1123. })).await.unwrap();
  1124. assert_eq!(ack.len(), 5);
  1125. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  1126. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1127. client: 0,
  1128. item_id: 0x10000,
  1129. amount: 2,
  1130. ..
  1131. }),
  1132. ..
  1133. }))));
  1134. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  1135. msg: GameMessage::CreateItem(CreateItem {
  1136. client: 1,
  1137. item_id: 0x810001,
  1138. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  1139. ..
  1140. }),
  1141. ..
  1142. }))));
  1143. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  1144. msg: GameMessage::CreateItem(CreateItem {
  1145. client: 1,
  1146. item_id: 0x810001,
  1147. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  1148. ..
  1149. }),
  1150. ..
  1151. }))));
  1152. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  1153. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  1154. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1155. assert_eq!(p1_items.items.len(), 1);
  1156. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  1157. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  1158. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1159. assert_eq!(p2_items.items.len(), 1);
  1160. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 5);
  1161. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  1162. }
  1163. #[async_std::test]
  1164. async fn test_trade_individual_for_stacked() {
  1165. let mut entity_gateway = InMemoryGateway::default();
  1166. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1167. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1168. let p1_inv = vec![
  1169. entity_gateway.create_item(
  1170. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  1171. .as_new()
  1172. ).await.unwrap()];
  1173. let p2_stack = futures::future::join_all((0..2).map(|_| {
  1174. let mut entity_gateway = entity_gateway.clone();
  1175. async move {
  1176. entity_gateway.create_item(
  1177. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1178. .as_new()
  1179. ).await
  1180. }}))
  1181. .await
  1182. .into_iter()
  1183. .collect::<Result<Vec<ItemEntity>,_>>()
  1184. .unwrap();
  1185. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  1186. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  1187. let mut ship = standard_ship(entity_gateway.clone());
  1188. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1189. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1190. join_lobby(&mut ship, ClientId(1)).await;
  1191. join_lobby(&mut ship, ClientId(2)).await;
  1192. create_room(&mut ship, ClientId(1), "room", "").await;
  1193. join_room(&mut ship, ClientId(2), 0).await;
  1194. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1195. assert_eq!(p1_items.items.len(), 1);
  1196. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1197. assert_eq!(p2_items.items.len(), 1);
  1198. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1199. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1200. client: 1,
  1201. target: 0,
  1202. trade: TradeRequestCommand::AddItem(0x10000, 1)
  1203. })))).await.unwrap();
  1204. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  1205. client: 0,
  1206. target: 0,
  1207. trade: TradeRequestCommand::AddItem(0x210000, 2)
  1208. })))).await.unwrap();
  1209. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1210. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1211. let titems = TradeItemBuilder::default()
  1212. .individual(&p1_items.items[0], 0x10000)
  1213. .build();
  1214. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1215. trade_target: 1,
  1216. unknown2: 0,
  1217. count: 1,
  1218. items: titems,
  1219. })).await.unwrap();
  1220. assert_eq!(ack.len(), 0);
  1221. let titems = TradeItemBuilder::default()
  1222. .stacked(&p2_items.items[0], 0x210000, 2)
  1223. .build();
  1224. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1225. trade_target: 0,
  1226. unknown2: 0,
  1227. count: 1,
  1228. items: titems,
  1229. })).await.unwrap();
  1230. assert_eq!(ack.len(), 2);
  1231. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1232. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1233. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1234. })).await.unwrap();
  1235. assert_eq!(ack.len(), 0);
  1236. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1237. })).await.unwrap();
  1238. assert_eq!(ack.len(), 8);
  1239. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  1240. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1241. client: 1,
  1242. item_id: 0x210000,
  1243. ..
  1244. }),
  1245. ..
  1246. }))));
  1247. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  1248. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1249. client: 0,
  1250. item_id: 0x10000,
  1251. ..
  1252. }),
  1253. ..
  1254. }))));
  1255. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  1256. msg: GameMessage::CreateItem(CreateItem {
  1257. client: 1,
  1258. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  1259. item_id: 0x810002,
  1260. ..
  1261. }),
  1262. ..
  1263. }))));
  1264. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1265. msg: GameMessage::CreateItem(CreateItem {
  1266. client: 1,
  1267. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  1268. item_id: 0x810002,
  1269. ..
  1270. }),
  1271. ..
  1272. }))));
  1273. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1274. msg: GameMessage::CreateItem(CreateItem {
  1275. client: 0,
  1276. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  1277. item_id: 0x810001,
  1278. ..
  1279. }),
  1280. ..
  1281. }))));
  1282. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1283. msg: GameMessage::CreateItem(CreateItem {
  1284. client: 0,
  1285. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  1286. item_id: 0x810001,
  1287. ..
  1288. }),
  1289. ..
  1290. }))));
  1291. assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  1292. assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  1293. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1294. assert_eq!(p1_items.items.len(), 1);
  1295. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  1296. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  1297. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1298. assert_eq!(p2_items.items.len(), 1);
  1299. assert!(matches!(p2_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Saber, ..}), ..}));
  1300. }
  1301. #[async_std::test]
  1302. async fn test_trade_multiple_individual() {
  1303. let mut entity_gateway = InMemoryGateway::default();
  1304. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1305. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1306. let p1_inv = vec![
  1307. entity_gateway.create_item(
  1308. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  1309. .as_new()
  1310. ).await.unwrap(),
  1311. entity_gateway.create_item(
  1312. ItemBuilder::weapon(item::weapon::WeaponType::Buster)
  1313. .as_new()
  1314. ).await.unwrap(),
  1315. ];
  1316. let p2_inv = vec![
  1317. entity_gateway.create_item(
  1318. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  1319. .as_new()
  1320. ).await.unwrap(),
  1321. entity_gateway.create_item(
  1322. ItemBuilder::weapon(item::weapon::WeaponType::Autogun)
  1323. .as_new()
  1324. ).await.unwrap(),
  1325. ];
  1326. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  1327. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  1328. let mut ship = standard_ship(entity_gateway.clone());
  1329. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1330. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1331. join_lobby(&mut ship, ClientId(1)).await;
  1332. join_lobby(&mut ship, ClientId(2)).await;
  1333. create_room(&mut ship, ClientId(1), "room", "").await;
  1334. join_room(&mut ship, ClientId(2), 0).await;
  1335. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1336. assert_eq!(p1_items.items.len(), 2);
  1337. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1338. assert_eq!(p2_items.items.len(), 2);
  1339. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1340. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1341. client: 1,
  1342. target: 0,
  1343. trade: TradeRequestCommand::AddItem(0x10000, 1)
  1344. })))).await.unwrap();
  1345. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1346. client: 1,
  1347. target: 0,
  1348. trade: TradeRequestCommand::AddItem(0x10001, 1)
  1349. })))).await.unwrap();
  1350. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  1351. client: 0,
  1352. target: 0,
  1353. trade: TradeRequestCommand::AddItem(0x210000, 1)
  1354. })))).await.unwrap();
  1355. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  1356. client: 0,
  1357. target: 0,
  1358. trade: TradeRequestCommand::AddItem(0x210001, 1)
  1359. })))).await.unwrap();
  1360. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1361. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1362. let titems = TradeItemBuilder::default()
  1363. .individual(&p1_items.items[0], 0x10000)
  1364. .individual(&p1_items.items[1], 0x10001)
  1365. .build();
  1366. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1367. trade_target: 1,
  1368. unknown2: 0,
  1369. count: 2,
  1370. items: titems,
  1371. })).await.unwrap();
  1372. assert_eq!(ack.len(), 0);
  1373. let titems = TradeItemBuilder::default()
  1374. .individual(&p2_items.items[0], 0x210000)
  1375. .individual(&p2_items.items[1], 0x210001)
  1376. .build();
  1377. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1378. trade_target: 0,
  1379. unknown2: 0,
  1380. count: 2,
  1381. items: titems,
  1382. })).await.unwrap();
  1383. assert_eq!(ack.len(), 2);
  1384. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1385. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1386. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1387. })).await.unwrap();
  1388. assert_eq!(ack.len(), 0);
  1389. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1390. })).await.unwrap();
  1391. assert_eq!(ack.len(), 14);
  1392. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  1393. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1394. client: 1,
  1395. item_id: 0x210000,
  1396. ..
  1397. }),
  1398. ..
  1399. }))));
  1400. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  1401. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1402. client: 1,
  1403. item_id: 0x210001,
  1404. ..
  1405. }),
  1406. ..
  1407. }))));
  1408. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  1409. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1410. client: 0,
  1411. item_id: 0x10000,
  1412. ..
  1413. }),
  1414. ..
  1415. }))));
  1416. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1417. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1418. client: 0,
  1419. item_id: 0x10001,
  1420. ..
  1421. }),
  1422. ..
  1423. }))));
  1424. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1425. msg: GameMessage::CreateItem(CreateItem {
  1426. client: 1,
  1427. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1428. item_id: 0x810004,
  1429. ..
  1430. }),
  1431. ..
  1432. }))));
  1433. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1434. msg: GameMessage::CreateItem(CreateItem {
  1435. client: 1,
  1436. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1437. item_id: 0x810004,
  1438. ..
  1439. }),
  1440. ..
  1441. }))));
  1442. assert!(matches!(ack[6], (ClientId(1), SendShipPacket::Message(Message {
  1443. msg: GameMessage::CreateItem(CreateItem {
  1444. client: 1,
  1445. item_data: [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1446. item_id: 0x810003,
  1447. ..
  1448. }),
  1449. ..
  1450. }))));
  1451. assert!(matches!(ack[7], (ClientId(2), SendShipPacket::Message(Message {
  1452. msg: GameMessage::CreateItem(CreateItem {
  1453. client: 1,
  1454. item_data: [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1455. item_id: 0x810003,
  1456. ..
  1457. }),
  1458. ..
  1459. }))));
  1460. assert!(matches!(ack[8], (ClientId(1), SendShipPacket::Message(Message {
  1461. msg: GameMessage::CreateItem(CreateItem {
  1462. client: 0,
  1463. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1464. item_id: 0x810002,
  1465. ..
  1466. }),
  1467. ..
  1468. }))));
  1469. assert!(matches!(ack[9], (ClientId(2), SendShipPacket::Message(Message {
  1470. msg: GameMessage::CreateItem(CreateItem {
  1471. client: 0,
  1472. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1473. item_id: 0x810002,
  1474. ..
  1475. }),
  1476. ..
  1477. }))));
  1478. assert!(matches!(ack[10], (ClientId(1), SendShipPacket::Message(Message {
  1479. msg: GameMessage::CreateItem(CreateItem {
  1480. client: 0,
  1481. item_data: [0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1482. item_id: 0x810001,
  1483. ..
  1484. }),
  1485. ..
  1486. }))));
  1487. assert!(matches!(ack[11], (ClientId(2), SendShipPacket::Message(Message {
  1488. msg: GameMessage::CreateItem(CreateItem {
  1489. client: 0,
  1490. item_data: [0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1491. item_id: 0x810001,
  1492. ..
  1493. }),
  1494. ..
  1495. }))));
  1496. assert!(matches!(ack[12], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  1497. assert!(matches!(ack[13], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  1498. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1499. assert_eq!(p1_items.items.len(), 2);
  1500. assert!(matches!(p1_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Handgun, ..}), ..}));
  1501. assert!(matches!(p1_items.items[1].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Autogun, ..}), ..}));
  1502. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1503. assert_eq!(p2_items.items.len(), 2);
  1504. assert!(matches!(p2_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Saber, ..}), ..}));
  1505. assert!(matches!(p2_items.items[1].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Buster, ..}), ..}));
  1506. }
  1507. #[async_std::test]
  1508. async fn test_trade_multiple_stacked() {
  1509. let mut entity_gateway = InMemoryGateway::default();
  1510. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1511. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1512. let p1_stack1 = futures::future::join_all((0..2).map(|_| {
  1513. let mut entity_gateway = entity_gateway.clone();
  1514. async move {
  1515. entity_gateway.create_item(
  1516. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1517. .as_new()
  1518. ).await
  1519. }}))
  1520. .await
  1521. .into_iter()
  1522. .collect::<Result<Vec<ItemEntity>,_>>()
  1523. .unwrap();
  1524. let p1_stack2 = futures::future::join_all((0..2).map(|_| {
  1525. let mut entity_gateway = entity_gateway.clone();
  1526. async move {
  1527. entity_gateway.create_item(
  1528. ItemBuilder::tool(item::tool::ToolType::Dimate)
  1529. .as_new()
  1530. ).await
  1531. }}))
  1532. .await
  1533. .into_iter()
  1534. .collect::<Result<Vec<ItemEntity>,_>>()
  1535. .unwrap();
  1536. let p2_stack1 = futures::future::join_all((0..3).map(|_| {
  1537. let mut entity_gateway = entity_gateway.clone();
  1538. async move {
  1539. entity_gateway.create_item(
  1540. ItemBuilder::tool(item::tool::ToolType::Monofluid)
  1541. .as_new()
  1542. ).await
  1543. }}))
  1544. .await
  1545. .into_iter()
  1546. .collect::<Result<Vec<ItemEntity>,_>>()
  1547. .unwrap();
  1548. let p2_stack2 = futures::future::join_all((0..3).map(|_| {
  1549. let mut entity_gateway = entity_gateway.clone();
  1550. async move {
  1551. entity_gateway.create_item(
  1552. ItemBuilder::tool(item::tool::ToolType::Difluid)
  1553. .as_new()
  1554. ).await
  1555. }}))
  1556. .await
  1557. .into_iter()
  1558. .collect::<Result<Vec<ItemEntity>,_>>()
  1559. .unwrap();
  1560. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
  1561. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack1, p2_stack2])).await.unwrap();
  1562. let mut ship = standard_ship(entity_gateway.clone());
  1563. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1564. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1565. join_lobby(&mut ship, ClientId(1)).await;
  1566. join_lobby(&mut ship, ClientId(2)).await;
  1567. create_room(&mut ship, ClientId(1), "room", "").await;
  1568. join_room(&mut ship, ClientId(2), 0).await;
  1569. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1570. assert_eq!(p1_items.items.len(), 2);
  1571. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1572. assert_eq!(p2_items.items.len(), 2);
  1573. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1574. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1575. client: 1,
  1576. target: 0,
  1577. trade: TradeRequestCommand::AddItem(0x10000, 2)
  1578. })))).await.unwrap();
  1579. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1580. client: 1,
  1581. target: 0,
  1582. trade: TradeRequestCommand::AddItem(0x10001, 2)
  1583. })))).await.unwrap();
  1584. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  1585. client: 0,
  1586. target: 0,
  1587. trade: TradeRequestCommand::AddItem(0x210000, 3)
  1588. })))).await.unwrap();
  1589. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  1590. client: 0,
  1591. target: 0,
  1592. trade: TradeRequestCommand::AddItem(0x210001, 3)
  1593. })))).await.unwrap();
  1594. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1595. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1596. let titems = TradeItemBuilder::default()
  1597. .stacked(&p1_items.items[0], 0x10000, 2)
  1598. .stacked(&p1_items.items[1], 0x10001, 2)
  1599. .build();
  1600. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1601. trade_target: 1,
  1602. unknown2: 0,
  1603. count: 2,
  1604. items: titems,
  1605. })).await.unwrap();
  1606. assert_eq!(ack.len(), 0);
  1607. let titems = TradeItemBuilder::default()
  1608. .stacked(&p2_items.items[0], 0x210000, 3)
  1609. .stacked(&p2_items.items[1], 0x210001, 3)
  1610. .build();
  1611. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1612. trade_target: 0,
  1613. unknown2: 0,
  1614. count: 2,
  1615. items: titems,
  1616. })).await.unwrap();
  1617. assert_eq!(ack.len(), 2);
  1618. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1619. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1620. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1621. })).await.unwrap();
  1622. assert_eq!(ack.len(), 0);
  1623. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1624. })).await.unwrap();
  1625. assert_eq!(ack.len(), 14);
  1626. assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
  1627. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1628. client: 1,
  1629. item_id: 0x210000,
  1630. ..
  1631. }),
  1632. ..
  1633. }))));
  1634. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  1635. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1636. client: 1,
  1637. item_id: 0x210001,
  1638. ..
  1639. }),
  1640. ..
  1641. }))));
  1642. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  1643. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1644. client: 0,
  1645. item_id: 0x10000,
  1646. ..
  1647. }),
  1648. ..
  1649. }))));
  1650. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1651. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1652. client: 0,
  1653. item_id: 0x10001,
  1654. ..
  1655. }),
  1656. ..
  1657. }))));
  1658. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1659. msg: GameMessage::CreateItem(CreateItem {
  1660. client: 1,
  1661. item_id: 0x810004,
  1662. ..
  1663. }),
  1664. ..
  1665. }))));
  1666. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1667. msg: GameMessage::CreateItem(CreateItem {
  1668. client: 1,
  1669. item_id: 0x810004,
  1670. ..
  1671. }),
  1672. ..
  1673. }))));
  1674. assert!(matches!(ack[6], (ClientId(1), SendShipPacket::Message(Message {
  1675. msg: GameMessage::CreateItem(CreateItem {
  1676. client: 1,
  1677. item_id: 0x810003,
  1678. ..
  1679. }),
  1680. ..
  1681. }))));
  1682. assert!(matches!(ack[7], (ClientId(2), SendShipPacket::Message(Message {
  1683. msg: GameMessage::CreateItem(CreateItem {
  1684. client: 1,
  1685. item_id: 0x810003,
  1686. ..
  1687. }),
  1688. ..
  1689. }))));
  1690. assert!(matches!(ack[8], (ClientId(1), SendShipPacket::Message(Message {
  1691. msg: GameMessage::CreateItem(CreateItem {
  1692. client: 0,
  1693. item_id: 0x810002,
  1694. ..
  1695. }),
  1696. ..
  1697. }))));
  1698. assert!(matches!(ack[9], (ClientId(2), SendShipPacket::Message(Message {
  1699. msg: GameMessage::CreateItem(CreateItem {
  1700. client: 0,
  1701. item_id: 0x810002,
  1702. ..
  1703. }),
  1704. ..
  1705. }))));
  1706. assert!(matches!(ack[10], (ClientId(1), SendShipPacket::Message(Message {
  1707. msg: GameMessage::CreateItem(CreateItem {
  1708. client: 0,
  1709. item_id: 0x810001,
  1710. ..
  1711. }),
  1712. ..
  1713. }))));
  1714. assert!(matches!(ack[11], (ClientId(2), SendShipPacket::Message(Message {
  1715. msg: GameMessage::CreateItem(CreateItem {
  1716. client: 0,
  1717. item_id: 0x810001,
  1718. ..
  1719. }),
  1720. ..
  1721. }))));
  1722. assert!(matches!(ack[12], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  1723. assert!(matches!(ack[13], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  1724. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1725. assert_eq!(p1_items.items.len(), 2);
  1726. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 3);
  1727. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
  1728. assert_eq!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 3);
  1729. assert!(matches!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Difluid, ..}), ..}));
  1730. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1731. assert_eq!(p2_items.items.len(), 2);
  1732. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  1733. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  1734. assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
  1735. assert!(matches!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Dimate, ..}), ..}));
  1736. }
  1737. #[async_std::test]
  1738. async fn test_trade_not_enough_inventory_space_individual() {
  1739. let mut entity_gateway = InMemoryGateway::default();
  1740. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1741. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1742. let p1_inv = futures::future::join_all((0..2).map(|_| {
  1743. let mut entity_gateway = entity_gateway.clone();
  1744. async move {
  1745. entity_gateway.create_item(
  1746. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  1747. .as_new()
  1748. ).await
  1749. }}))
  1750. .await
  1751. .into_iter()
  1752. .collect::<Result<Vec<ItemEntity>,_>>()
  1753. .unwrap();
  1754. let p2_inv = futures::future::join_all((0..30).map(|_| {
  1755. let mut entity_gateway = entity_gateway.clone();
  1756. async move {
  1757. entity_gateway.create_item(
  1758. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  1759. .as_new()
  1760. ).await
  1761. }}))
  1762. .await
  1763. .into_iter()
  1764. .collect::<Result<Vec<ItemEntity>,_>>()
  1765. .unwrap();
  1766. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  1767. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  1768. let mut ship = standard_ship(entity_gateway.clone());
  1769. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1770. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1771. join_lobby(&mut ship, ClientId(1)).await;
  1772. join_lobby(&mut ship, ClientId(2)).await;
  1773. create_room(&mut ship, ClientId(1), "room", "").await;
  1774. join_room(&mut ship, ClientId(2), 0).await;
  1775. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1776. assert_eq!(p1_items.items.len(), 2);
  1777. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1778. assert_eq!(p2_items.items.len(), 30);
  1779. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1780. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1781. client: 1,
  1782. target: 0,
  1783. trade: TradeRequestCommand::AddItem(0x10000, 1)
  1784. })))).await.unwrap();
  1785. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1786. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1787. let titems = TradeItemBuilder::default()
  1788. .individual(&p1_items.items[0], 0x10000)
  1789. .build();
  1790. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1791. trade_target: 1,
  1792. unknown2: 0,
  1793. count: 1,
  1794. items: titems,
  1795. })).await.unwrap();
  1796. assert_eq!(ack.len(), 0);
  1797. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1798. trade_target: 0,
  1799. unknown2: 0,
  1800. count: 0,
  1801. items: Default::default(),
  1802. })).await.unwrap();
  1803. assert_eq!(ack.len(), 2);
  1804. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1805. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1806. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1807. })).await.unwrap();
  1808. assert_eq!(ack.len(), 0);
  1809. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1810. })).await.unwrap();
  1811. assert_eq!(ack,
  1812. vec![
  1813. (ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
  1814. (ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
  1815. ]);
  1816. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1817. assert_eq!(p1_items.items.len(), 2);
  1818. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1819. assert_eq!(p2_items.items.len(), 30);
  1820. }
  1821. #[async_std::test]
  1822. async fn test_trade_not_enough_inventory_space_stacked() {
  1823. let mut entity_gateway = InMemoryGateway::default();
  1824. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1825. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1826. let p1_stack = futures::future::join_all((0..2).map(|_| {
  1827. let mut entity_gateway = entity_gateway.clone();
  1828. async move {
  1829. entity_gateway.create_item(
  1830. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1831. .as_new()
  1832. ).await
  1833. }}))
  1834. .await
  1835. .into_iter()
  1836. .collect::<Result<Vec<ItemEntity>,_>>()
  1837. .unwrap();
  1838. let p2_inv = futures::future::join_all((0..30).map(|_| {
  1839. let mut entity_gateway = entity_gateway.clone();
  1840. async move {
  1841. entity_gateway.create_item(
  1842. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  1843. .as_new()
  1844. ).await
  1845. }}))
  1846. .await
  1847. .into_iter()
  1848. .collect::<Result<Vec<ItemEntity>,_>>()
  1849. .unwrap();
  1850. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  1851. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  1852. let mut ship = standard_ship(entity_gateway.clone());
  1853. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1854. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1855. join_lobby(&mut ship, ClientId(1)).await;
  1856. join_lobby(&mut ship, ClientId(2)).await;
  1857. create_room(&mut ship, ClientId(1), "room", "").await;
  1858. join_room(&mut ship, ClientId(2), 0).await;
  1859. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1860. assert_eq!(p1_items.items.len(), 1);
  1861. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1862. assert_eq!(p2_items.items.len(), 30);
  1863. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1864. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1865. client: 1,
  1866. target: 0,
  1867. trade: TradeRequestCommand::AddItem(0x10000, 2)
  1868. })))).await.unwrap();
  1869. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1870. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1871. let titems = TradeItemBuilder::default()
  1872. .stacked(&p1_items.items[0], 0x10000, 2)
  1873. .build();
  1874. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1875. trade_target: 1,
  1876. unknown2: 0,
  1877. count: 1,
  1878. items: titems,
  1879. })).await.unwrap();
  1880. assert_eq!(ack.len(), 0);
  1881. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1882. trade_target: 0,
  1883. unknown2: 0,
  1884. count: 0,
  1885. items: Default::default(),
  1886. })).await.unwrap();
  1887. assert_eq!(ack.len(), 2);
  1888. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1889. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1890. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1891. })).await.unwrap();
  1892. assert_eq!(ack.len(), 0);
  1893. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1894. })).await.unwrap();
  1895. assert_eq!(ack,
  1896. vec![
  1897. (ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
  1898. (ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
  1899. ]);
  1900. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1901. assert_eq!(p1_items.items.len(), 1);
  1902. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1903. assert_eq!(p2_items.items.len(), 30);
  1904. }
  1905. #[async_std::test]
  1906. async fn test_trade_stack_too_big() {
  1907. let mut entity_gateway = InMemoryGateway::default();
  1908. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1909. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1910. let p1_stack = futures::future::join_all((0..8).map(|_| {
  1911. let mut entity_gateway = entity_gateway.clone();
  1912. async move {
  1913. entity_gateway.create_item(
  1914. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1915. .as_new()
  1916. ).await
  1917. }}))
  1918. .await
  1919. .into_iter()
  1920. .collect::<Result<Vec<ItemEntity>,_>>()
  1921. .unwrap();
  1922. let p2_stack = futures::future::join_all((0..7).map(|_| {
  1923. let mut entity_gateway = entity_gateway.clone();
  1924. async move {
  1925. entity_gateway.create_item(
  1926. ItemBuilder::tool(item::tool::ToolType::Monomate)
  1927. .as_new()
  1928. ).await
  1929. }}))
  1930. .await
  1931. .into_iter()
  1932. .collect::<Result<Vec<ItemEntity>,_>>()
  1933. .unwrap();
  1934. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  1935. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  1936. let mut ship = standard_ship(entity_gateway.clone());
  1937. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1938. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1939. join_lobby(&mut ship, ClientId(1)).await;
  1940. join_lobby(&mut ship, ClientId(2)).await;
  1941. create_room(&mut ship, ClientId(1), "room", "").await;
  1942. join_room(&mut ship, ClientId(2), 0).await;
  1943. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1944. assert_eq!(p1_items.items.len(), 1);
  1945. assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 8);
  1946. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1947. assert_eq!(p2_items.items.len(), 1);
  1948. assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 7);
  1949. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1950. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  1951. client: 1,
  1952. target: 0,
  1953. trade: TradeRequestCommand::AddItem(0x10000, 4)
  1954. })))).await.unwrap();
  1955. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1956. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  1957. let titems = TradeItemBuilder::default()
  1958. .stacked(&p1_items.items[0], 0x10000, 4)
  1959. .build();
  1960. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1961. trade_target: 1,
  1962. unknown2: 0,
  1963. count: 1,
  1964. items: titems,
  1965. })).await.unwrap();
  1966. assert_eq!(ack.len(), 0);
  1967. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  1968. trade_target: 0,
  1969. unknown2: 0,
  1970. count: 0,
  1971. items: Default::default(),
  1972. })).await.unwrap();
  1973. assert_eq!(ack.len(), 2);
  1974. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1975. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  1976. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1977. })).await.unwrap();
  1978. assert_eq!(ack.len(), 0);
  1979. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  1980. })).await.unwrap();
  1981. assert_eq!(ack,
  1982. vec![
  1983. (ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
  1984. (ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
  1985. ]);
  1986. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1987. assert_eq!(p1_items.items.len(), 1);
  1988. assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 8);
  1989. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  1990. assert_eq!(p2_items.items.len(), 1);
  1991. assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 7);
  1992. }
  1993. #[async_std::test]
  1994. async fn test_trade_meseta() {
  1995. let mut entity_gateway = InMemoryGateway::default();
  1996. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1997. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1998. entity_gateway.set_character_meseta(&char1.id, Meseta(2323)).await.unwrap();
  1999. let mut ship = standard_ship(entity_gateway.clone());
  2000. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2001. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2002. join_lobby(&mut ship, ClientId(1)).await;
  2003. join_lobby(&mut ship, ClientId(2)).await;
  2004. create_room(&mut ship, ClientId(1), "room", "").await;
  2005. join_room(&mut ship, ClientId(2), 0).await;
  2006. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2007. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2008. client: 1,
  2009. target: 0,
  2010. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 23)
  2011. })))).await.unwrap();
  2012. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2013. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2014. let titems = TradeItemBuilder::default()
  2015. .meseta(23)
  2016. .build();
  2017. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2018. trade_target: 1,
  2019. unknown2: 0,
  2020. count: 1,
  2021. items: titems,
  2022. })).await.unwrap();
  2023. assert_eq!(ack.len(), 0);
  2024. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2025. trade_target: 0,
  2026. unknown2: 0,
  2027. count: 0,
  2028. items: Default::default(),
  2029. })).await.unwrap();
  2030. assert_eq!(ack.len(), 2);
  2031. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2032. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2033. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2034. })).await.unwrap();
  2035. assert_eq!(ack.len(), 0);
  2036. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2037. })).await.unwrap();
  2038. assert_eq!(ack.len(), 5);
  2039. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2040. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2041. ..
  2042. }))));
  2043. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2044. msg: GameMessage::CreateItem(CreateItem {..}),
  2045. ..
  2046. }))));
  2047. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2048. msg: GameMessage::CreateItem(CreateItem {..}),
  2049. ..
  2050. }))));
  2051. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2052. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2053. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2054. assert_eq!(c1_meseta, Meseta(2300));
  2055. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2056. assert_eq!(c2_meseta, Meseta(23));
  2057. }
  2058. #[async_std::test]
  2059. async fn test_trade_too_much_meseta() {
  2060. let mut entity_gateway = InMemoryGateway::default();
  2061. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2062. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2063. entity_gateway.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
  2064. entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
  2065. let mut ship = standard_ship(entity_gateway.clone());
  2066. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2067. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2068. join_lobby(&mut ship, ClientId(1)).await;
  2069. join_lobby(&mut ship, ClientId(2)).await;
  2070. create_room(&mut ship, ClientId(1), "room", "").await;
  2071. join_room(&mut ship, ClientId(2), 0).await;
  2072. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2073. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2074. client: 1,
  2075. target: 0,
  2076. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 2000)
  2077. })))).await.unwrap();
  2078. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2079. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2080. let titems = TradeItemBuilder::default()
  2081. .meseta(2000)
  2082. .build();
  2083. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2084. trade_target: 1,
  2085. unknown2: 0,
  2086. count: 1,
  2087. items: titems,
  2088. })).await.unwrap();
  2089. assert_eq!(ack.len(), 2);
  2090. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2091. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2092. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2093. assert_eq!(c1_meseta, Meseta(4000));
  2094. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2095. assert_eq!(c2_meseta, Meseta(999000));
  2096. }
  2097. #[async_std::test]
  2098. async fn test_trade_invalid_amount_of_meseta() {
  2099. let mut entity_gateway = InMemoryGateway::default();
  2100. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2101. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2102. entity_gateway.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
  2103. entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
  2104. let mut ship = standard_ship(entity_gateway.clone());
  2105. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2106. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2107. join_lobby(&mut ship, ClientId(1)).await;
  2108. join_lobby(&mut ship, ClientId(2)).await;
  2109. create_room(&mut ship, ClientId(1), "room", "").await;
  2110. join_room(&mut ship, ClientId(2), 0).await;
  2111. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2112. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2113. client: 1,
  2114. target: 0,
  2115. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 5000)
  2116. })))).await.unwrap();
  2117. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2118. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2119. let titems = TradeItemBuilder::default()
  2120. .meseta(5000)
  2121. .build();
  2122. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2123. trade_target: 1,
  2124. unknown2: 0,
  2125. count: 1,
  2126. items: titems,
  2127. })).await.unwrap();
  2128. assert_eq!(ack.len(), 2);
  2129. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2130. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2131. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2132. assert_eq!(c1_meseta, Meseta(4000));
  2133. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2134. assert_eq!(c2_meseta, Meseta(999000));
  2135. }
  2136. #[async_std::test]
  2137. async fn test_trade_meseta_request_and_items_dont_match() {
  2138. let mut entity_gateway = InMemoryGateway::default();
  2139. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2140. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2141. entity_gateway.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
  2142. entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
  2143. let mut ship = standard_ship(entity_gateway.clone());
  2144. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2145. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2146. join_lobby(&mut ship, ClientId(1)).await;
  2147. join_lobby(&mut ship, ClientId(2)).await;
  2148. create_room(&mut ship, ClientId(1), "room", "").await;
  2149. join_room(&mut ship, ClientId(2), 0).await;
  2150. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2151. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2152. client: 1,
  2153. target: 0,
  2154. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 50)
  2155. })))).await.unwrap();
  2156. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2157. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2158. let titems = TradeItemBuilder::default()
  2159. .meseta(23)
  2160. .build();
  2161. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2162. trade_target: 1,
  2163. unknown2: 0,
  2164. count: 1,
  2165. items: titems,
  2166. })).await.unwrap();
  2167. assert_eq!(ack.len(), 2);
  2168. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2169. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2170. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2171. assert_eq!(c1_meseta, Meseta(4000));
  2172. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2173. assert_eq!(c2_meseta, Meseta(999000));
  2174. }
  2175. #[async_std::test]
  2176. async fn test_player_declined_trade() {
  2177. let mut entity_gateway = InMemoryGateway::default();
  2178. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2179. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2180. let mut ship = standard_ship(entity_gateway.clone());
  2181. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2182. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2183. join_lobby(&mut ship, ClientId(1)).await;
  2184. join_lobby(&mut ship, ClientId(2)).await;
  2185. create_room(&mut ship, ClientId(1), "room", "").await;
  2186. join_room(&mut ship, ClientId(2), 0).await;
  2187. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2188. let ack = ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2189. client: 1,
  2190. target: 0,
  2191. trade: TradeRequestCommand::Cancel
  2192. })))).await.unwrap();
  2193. assert_eq!(ack.len(), 2);
  2194. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2195. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2196. }
  2197. #[async_std::test]
  2198. async fn test_back_out_of_trade_last_minute() {
  2199. let mut entity_gateway = InMemoryGateway::default();
  2200. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2201. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2202. let mut p1_inv = Vec::new();
  2203. p1_inv.push(entity_gateway.create_item(
  2204. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  2205. .as_new()
  2206. ).await.unwrap());
  2207. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2208. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2209. let mut ship = standard_ship(entity_gateway.clone());
  2210. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2211. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2212. join_lobby(&mut ship, ClientId(1)).await;
  2213. join_lobby(&mut ship, ClientId(2)).await;
  2214. create_room(&mut ship, ClientId(1), "room", "").await;
  2215. join_room(&mut ship, ClientId(2), 0).await;
  2216. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2217. assert_eq!(p1_items.items.len(), 1);
  2218. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2219. assert_eq!(p2_items.items.len(), 0);
  2220. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2221. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2222. client: 1,
  2223. target: 0,
  2224. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2225. })))).await.unwrap();
  2226. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2227. let ack = ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2228. client: 1,
  2229. target: 0,
  2230. trade: TradeRequestCommand::Cancel
  2231. })))).await.unwrap();
  2232. assert_eq!(ack.len(), 2);
  2233. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2234. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2235. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2236. assert_eq!(p1_items.items.len(), 1);
  2237. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2238. assert_eq!(p2_items.items.len(), 0);
  2239. }
  2240. #[async_std::test]
  2241. async fn test_valid_trade_when_both_inventories_are_full() {
  2242. let mut entity_gateway = InMemoryGateway::default();
  2243. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2244. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2245. let p1_inv = futures::future::join_all((0..30).map(|_| {
  2246. let mut entity_gateway = entity_gateway.clone();
  2247. async move {
  2248. entity_gateway.create_item(
  2249. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  2250. .as_new()
  2251. ).await
  2252. }}))
  2253. .await
  2254. .into_iter()
  2255. .collect::<Result<Vec<ItemEntity>,_>>()
  2256. .unwrap();
  2257. let p2_inv = futures::future::join_all((0..30).map(|_| {
  2258. let mut entity_gateway = entity_gateway.clone();
  2259. async move {
  2260. entity_gateway.create_item(
  2261. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  2262. .as_new()
  2263. ).await
  2264. }}))
  2265. .await
  2266. .into_iter()
  2267. .collect::<Result<Vec<ItemEntity>,_>>()
  2268. .unwrap();
  2269. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2270. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  2271. let mut ship = standard_ship(entity_gateway.clone());
  2272. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2273. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2274. join_lobby(&mut ship, ClientId(1)).await;
  2275. join_lobby(&mut ship, ClientId(2)).await;
  2276. create_room(&mut ship, ClientId(1), "room", "").await;
  2277. join_room(&mut ship, ClientId(2), 0).await;
  2278. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2279. assert_eq!(p1_items.items.len(), 30);
  2280. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2281. assert_eq!(p2_items.items.len(), 30);
  2282. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2283. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2284. client: 1,
  2285. target: 0,
  2286. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2287. })))).await.unwrap();
  2288. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2289. client: 1,
  2290. target: 0,
  2291. trade: TradeRequestCommand::AddItem(0x10001, 1)
  2292. })))).await.unwrap();
  2293. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2294. client: 0,
  2295. target: 0,
  2296. trade: TradeRequestCommand::AddItem(0x210000, 1)
  2297. })))).await.unwrap();
  2298. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2299. client: 0,
  2300. target: 0,
  2301. trade: TradeRequestCommand::AddItem(0x210001, 1)
  2302. })))).await.unwrap();
  2303. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2304. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2305. let titems = TradeItemBuilder::default()
  2306. .individual(&p1_items.items[0], 0x10000)
  2307. .individual(&p1_items.items[1], 0x10001)
  2308. .build();
  2309. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2310. trade_target: 1,
  2311. unknown2: 0,
  2312. count: 2,
  2313. items: titems,
  2314. })).await.unwrap();
  2315. assert_eq!(ack.len(), 0);
  2316. let titems = TradeItemBuilder::default()
  2317. .individual(&p2_items.items[0], 0x210000)
  2318. .individual(&p2_items.items[1], 0x210001)
  2319. .build();
  2320. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2321. trade_target: 0,
  2322. unknown2: 0,
  2323. count: 2,
  2324. items: titems,
  2325. })).await.unwrap();
  2326. assert_eq!(ack.len(), 2);
  2327. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2328. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2329. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2330. })).await.unwrap();
  2331. assert_eq!(ack.len(), 0);
  2332. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2333. })).await.unwrap();
  2334. assert_eq!(ack.len(), 14);
  2335. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2336. assert_eq!(p1_items.items.len(), 30);
  2337. assert_eq!(p1_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Saber, ..}, ..))).count(), 28);
  2338. assert_eq!(p1_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Handgun, ..}, ..))).count(), 2);
  2339. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2340. assert_eq!(p2_items.items.len(), 30);
  2341. assert_eq!(p2_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Saber, ..}, ..))).count(), 2);
  2342. assert_eq!(p2_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Handgun, ..}, ..))).count(), 28);
  2343. }
  2344. #[async_std::test]
  2345. async fn test_invalid_trade_when_both_inventories_are_full() {
  2346. let mut entity_gateway = InMemoryGateway::default();
  2347. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2348. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2349. let p1_inv = futures::future::join_all((0..30).map(|_| {
  2350. let mut entity_gateway = entity_gateway.clone();
  2351. async move {
  2352. entity_gateway.create_item(
  2353. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  2354. .as_new()
  2355. ).await
  2356. }}))
  2357. .await
  2358. .into_iter()
  2359. .collect::<Result<Vec<ItemEntity>,_>>()
  2360. .unwrap();
  2361. let p2_inv = futures::future::join_all((0..30).map(|_| {
  2362. let mut entity_gateway = entity_gateway.clone();
  2363. async move {
  2364. entity_gateway.create_item(
  2365. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  2366. .as_new()
  2367. ).await
  2368. }}))
  2369. .await
  2370. .into_iter()
  2371. .collect::<Result<Vec<ItemEntity>,_>>()
  2372. .unwrap();
  2373. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2374. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  2375. let mut ship = standard_ship(entity_gateway.clone());
  2376. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2377. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2378. join_lobby(&mut ship, ClientId(1)).await;
  2379. join_lobby(&mut ship, ClientId(2)).await;
  2380. create_room(&mut ship, ClientId(1), "room", "").await;
  2381. join_room(&mut ship, ClientId(2), 0).await;
  2382. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2383. assert_eq!(p1_items.items.len(), 30);
  2384. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2385. assert_eq!(p2_items.items.len(), 30);
  2386. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2387. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2388. client: 1,
  2389. target: 0,
  2390. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2391. })))).await.unwrap();
  2392. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2393. client: 1,
  2394. target: 0,
  2395. trade: TradeRequestCommand::AddItem(0x10001, 1)
  2396. })))).await.unwrap();
  2397. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2398. client: 1,
  2399. target: 0,
  2400. trade: TradeRequestCommand::AddItem(0x10002, 1)
  2401. })))).await.unwrap();
  2402. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2403. client: 0,
  2404. target: 0,
  2405. trade: TradeRequestCommand::AddItem(0x210000, 1)
  2406. })))).await.unwrap();
  2407. ship.handle(ClientId(2), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2408. client: 0,
  2409. target: 0,
  2410. trade: TradeRequestCommand::AddItem(0x210001, 1)
  2411. })))).await.unwrap();
  2412. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2413. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2414. let titems = TradeItemBuilder::default()
  2415. .individual(&p1_items.items[0], 0x10000)
  2416. .individual(&p1_items.items[1], 0x10001)
  2417. .individual(&p1_items.items[1], 0x10002)
  2418. .build();
  2419. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2420. trade_target: 1,
  2421. unknown2: 0,
  2422. count: 3,
  2423. items: titems,
  2424. })).await.unwrap();
  2425. assert_eq!(ack.len(), 0);
  2426. let titems = TradeItemBuilder::default()
  2427. .individual(&p2_items.items[0], 0x210000)
  2428. .individual(&p2_items.items[1], 0x210001)
  2429. .build();
  2430. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2431. trade_target: 0,
  2432. unknown2: 0,
  2433. count: 2,
  2434. items: titems,
  2435. })).await.unwrap();
  2436. assert_eq!(ack.len(), 2);
  2437. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2438. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2439. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2440. })).await.unwrap();
  2441. assert_eq!(ack.len(), 0);
  2442. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2443. })).await.unwrap();
  2444. assert_eq!(ack,
  2445. vec![
  2446. (ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
  2447. (ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
  2448. ]);
  2449. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2450. assert_eq!(p1_items.items.len(), 30);
  2451. assert_eq!(p1_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Saber, ..}, ..))).count(), 30);
  2452. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2453. assert_eq!(p2_items.items.len(), 30);
  2454. assert_eq!(p2_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Handgun, ..}, ..))).count(), 30);
  2455. }
  2456. #[async_std::test]
  2457. async fn test_client_tries_to_start_two_trades() {
  2458. let mut entity_gateway = InMemoryGateway::default();
  2459. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2460. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2461. let (_user2, _char3) = new_user_character(&mut entity_gateway, "a3", "a").await;
  2462. let mut ship = standard_ship(entity_gateway.clone());
  2463. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2464. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2465. log_in_char(&mut ship, ClientId(3), "a3", "a").await;
  2466. join_lobby(&mut ship, ClientId(1)).await;
  2467. join_lobby(&mut ship, ClientId(2)).await;
  2468. join_lobby(&mut ship, ClientId(3)).await;
  2469. create_room(&mut ship, ClientId(1), "room", "").await;
  2470. join_room(&mut ship, ClientId(2), 0).await;
  2471. join_room(&mut ship, ClientId(3), 0).await;
  2472. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2473. let ack = ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2474. client: 0,
  2475. target: 0,
  2476. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
  2477. })))).await.err().unwrap();
  2478. assert!(matches!(ack.downcast::<TradeError>().unwrap(), TradeError::ClientAlreadyInTrade));
  2479. }
  2480. #[async_std::test]
  2481. async fn test_client_tries_trading_with_client_already_trading() {
  2482. let mut entity_gateway = InMemoryGateway::default();
  2483. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2484. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2485. let (_user2, _char3) = new_user_character(&mut entity_gateway, "a3", "a").await;
  2486. let mut ship = standard_ship(entity_gateway.clone());
  2487. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2488. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2489. log_in_char(&mut ship, ClientId(3), "a3", "a").await;
  2490. join_lobby(&mut ship, ClientId(1)).await;
  2491. join_lobby(&mut ship, ClientId(2)).await;
  2492. join_lobby(&mut ship, ClientId(3)).await;
  2493. create_room(&mut ship, ClientId(1), "room", "").await;
  2494. join_room(&mut ship, ClientId(2), 0).await;
  2495. join_room(&mut ship, ClientId(3), 0).await;
  2496. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2497. let ack = ship.handle(ClientId(3), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2498. client: 2,
  2499. target: 0,
  2500. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
  2501. })))).await.err().unwrap();
  2502. assert!(matches!(ack.downcast::<TradeError>().unwrap(), TradeError::OtherAlreadyInTrade));
  2503. let ack = ship.handle(ClientId(3), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2504. client: 2,
  2505. target: 0,
  2506. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 1)
  2507. })))).await.err().unwrap();
  2508. assert!(matches!(ack.downcast::<TradeError>().unwrap(), TradeError::OtherAlreadyInTrade));
  2509. }
  2510. #[async_std::test]
  2511. async fn test_add_then_remove_individual_item() {
  2512. let mut entity_gateway = InMemoryGateway::default();
  2513. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2514. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2515. let mut p1_inv = Vec::new();
  2516. for _ in 0..2 {
  2517. p1_inv.push(entity_gateway.create_item(
  2518. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  2519. .as_new()
  2520. ).await.unwrap());
  2521. }
  2522. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2523. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2524. let mut ship = standard_ship(entity_gateway.clone());
  2525. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2526. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2527. join_lobby(&mut ship, ClientId(1)).await;
  2528. join_lobby(&mut ship, ClientId(2)).await;
  2529. create_room(&mut ship, ClientId(1), "room", "").await;
  2530. join_room(&mut ship, ClientId(2), 0).await;
  2531. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2532. assert_eq!(p1_items.items.len(), 2);
  2533. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2534. assert_eq!(p2_items.items.len(), 0);
  2535. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2536. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2537. client: 1,
  2538. target: 0,
  2539. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2540. })))).await.unwrap();
  2541. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2542. client: 1,
  2543. target: 0,
  2544. trade: TradeRequestCommand::AddItem(0x10001, 1)
  2545. })))).await.unwrap();
  2546. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2547. client: 1,
  2548. target: 0,
  2549. trade: TradeRequestCommand::RemoveItem(0x10000, 1)
  2550. })))).await.unwrap();
  2551. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2552. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2553. let titems = TradeItemBuilder::default()
  2554. .individual(&p1_items.items[1], 0x10001)
  2555. .build();
  2556. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2557. trade_target: 1,
  2558. unknown2: 0,
  2559. count: 1,
  2560. items: titems,
  2561. })).await.unwrap();
  2562. assert_eq!(ack.len(), 0);
  2563. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2564. trade_target: 0,
  2565. unknown2: 0,
  2566. count: 0,
  2567. items: Default::default(),
  2568. })).await.unwrap();
  2569. assert_eq!(ack.len(), 2);
  2570. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2571. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2572. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2573. })).await.unwrap();
  2574. assert_eq!(ack.len(), 0);
  2575. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2576. })).await.unwrap();
  2577. assert_eq!(ack.len(), 5);
  2578. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2579. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2580. ..
  2581. }))));
  2582. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2583. msg: GameMessage::CreateItem(CreateItem {..}),
  2584. ..
  2585. }))));
  2586. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2587. msg: GameMessage::CreateItem(CreateItem {..}),
  2588. ..
  2589. }))));
  2590. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2591. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2592. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2593. assert_eq!(p1_items.items.len(), 1);
  2594. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2595. assert_eq!(p2_items.items.len(), 1);
  2596. }
  2597. #[async_std::test]
  2598. async fn test_add_then_remove_stacked_item() {
  2599. let mut entity_gateway = InMemoryGateway::default();
  2600. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2601. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2602. let p1_stack1 = futures::future::join_all((0..2).map(|_| {
  2603. let mut entity_gateway = entity_gateway.clone();
  2604. async move {
  2605. entity_gateway.create_item(
  2606. ItemBuilder::tool(item::tool::ToolType::Monomate)
  2607. .as_new()
  2608. ).await
  2609. }}))
  2610. .await
  2611. .into_iter()
  2612. .collect::<Result<Vec<ItemEntity>,_>>()
  2613. .unwrap();
  2614. let p1_stack2 = futures::future::join_all((0..2).map(|_| {
  2615. let mut entity_gateway = entity_gateway.clone();
  2616. async move {
  2617. entity_gateway.create_item(
  2618. ItemBuilder::tool(item::tool::ToolType::Monofluid)
  2619. .as_new()
  2620. ).await
  2621. }}))
  2622. .await
  2623. .into_iter()
  2624. .collect::<Result<Vec<ItemEntity>,_>>()
  2625. .unwrap();
  2626. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
  2627. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2628. let mut ship = standard_ship(entity_gateway.clone());
  2629. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2630. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2631. join_lobby(&mut ship, ClientId(1)).await;
  2632. join_lobby(&mut ship, ClientId(2)).await;
  2633. create_room(&mut ship, ClientId(1), "room", "").await;
  2634. join_room(&mut ship, ClientId(2), 0).await;
  2635. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2636. assert_eq!(p1_items.items.len(), 2);
  2637. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2638. assert_eq!(p2_items.items.len(), 0);
  2639. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2640. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2641. client: 1,
  2642. target: 0,
  2643. trade: TradeRequestCommand::AddItem(0x10000, 2)
  2644. })))).await.unwrap();
  2645. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2646. client: 1,
  2647. target: 0,
  2648. trade: TradeRequestCommand::AddItem(0x10001, 2)
  2649. })))).await.unwrap();
  2650. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2651. client: 1,
  2652. target: 0,
  2653. trade: TradeRequestCommand::RemoveItem(0x10000, 2)
  2654. })))).await.unwrap();
  2655. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2656. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2657. let titems = TradeItemBuilder::default()
  2658. .stacked(&p1_items.items[1], 0x10001, 2)
  2659. .build();
  2660. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2661. trade_target: 1,
  2662. unknown2: 0,
  2663. count: 1,
  2664. items: titems,
  2665. })).await.unwrap();
  2666. assert_eq!(ack.len(), 0);
  2667. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2668. trade_target: 0,
  2669. unknown2: 0,
  2670. count: 0,
  2671. items: Default::default(),
  2672. })).await.unwrap();
  2673. assert_eq!(ack.len(), 2);
  2674. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2675. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2676. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2677. })).await.unwrap();
  2678. assert_eq!(ack.len(), 0);
  2679. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2680. })).await.unwrap();
  2681. assert_eq!(ack.len(), 5);
  2682. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2683. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2684. ..
  2685. }))));
  2686. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2687. msg: GameMessage::CreateItem(CreateItem {..}),
  2688. ..
  2689. }))));
  2690. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2691. msg: GameMessage::CreateItem(CreateItem {..}),
  2692. ..
  2693. }))));
  2694. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2695. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2696. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2697. assert_eq!(p1_items.items.len(), 1);
  2698. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  2699. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  2700. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2701. assert_eq!(p2_items.items.len(), 1);
  2702. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  2703. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
  2704. }
  2705. #[async_std::test]
  2706. async fn test_add_then_remove_partial_stack() {
  2707. let mut entity_gateway = InMemoryGateway::default();
  2708. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2709. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2710. let p1_stack1 = futures::future::join_all((0..2).map(|_| {
  2711. let mut entity_gateway = entity_gateway.clone();
  2712. async move {
  2713. entity_gateway.create_item(
  2714. ItemBuilder::tool(item::tool::ToolType::Monomate)
  2715. .as_new()
  2716. ).await
  2717. }}))
  2718. .await
  2719. .into_iter()
  2720. .collect::<Result<Vec<ItemEntity>,_>>()
  2721. .unwrap();
  2722. let p1_stack2 = futures::future::join_all((0..2).map(|_| {
  2723. let mut entity_gateway = entity_gateway.clone();
  2724. async move {
  2725. entity_gateway.create_item(
  2726. ItemBuilder::tool(item::tool::ToolType::Monofluid)
  2727. .as_new()
  2728. ).await
  2729. }}))
  2730. .await
  2731. .into_iter()
  2732. .collect::<Result<Vec<ItemEntity>,_>>()
  2733. .unwrap();
  2734. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
  2735. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2736. let mut ship = standard_ship(entity_gateway.clone());
  2737. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2738. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2739. join_lobby(&mut ship, ClientId(1)).await;
  2740. join_lobby(&mut ship, ClientId(2)).await;
  2741. create_room(&mut ship, ClientId(1), "room", "").await;
  2742. join_room(&mut ship, ClientId(2), 0).await;
  2743. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2744. assert_eq!(p1_items.items.len(), 2);
  2745. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2746. assert_eq!(p2_items.items.len(), 0);
  2747. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2748. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2749. client: 1,
  2750. target: 0,
  2751. trade: TradeRequestCommand::AddItem(0x10000, 2)
  2752. })))).await.unwrap();
  2753. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2754. client: 1,
  2755. target: 0,
  2756. trade: TradeRequestCommand::AddItem(0x10001, 2)
  2757. })))).await.unwrap();
  2758. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2759. client: 1,
  2760. target: 0,
  2761. trade: TradeRequestCommand::RemoveItem(0x10000, 1)
  2762. })))).await.unwrap();
  2763. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2764. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2765. let titems = TradeItemBuilder::default()
  2766. .stacked(&p1_items.items[0], 0x10000, 1)
  2767. .stacked(&p1_items.items[1], 0x10001, 2)
  2768. .build();
  2769. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2770. trade_target: 1,
  2771. unknown2: 0,
  2772. count: 2,
  2773. items: titems,
  2774. })).await.unwrap();
  2775. assert_eq!(ack.len(), 0);
  2776. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2777. trade_target: 0,
  2778. unknown2: 0,
  2779. count: 0,
  2780. items: Default::default(),
  2781. })).await.unwrap();
  2782. assert_eq!(ack.len(), 2);
  2783. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2784. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2785. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2786. })).await.unwrap();
  2787. assert_eq!(ack.len(), 0);
  2788. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2789. })).await.unwrap();
  2790. assert_eq!(ack.len(), 8);
  2791. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2792. assert_eq!(p1_items.items.len(), 1);
  2793. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  2794. assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  2795. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2796. assert_eq!(p2_items.items.len(), 2);
  2797. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  2798. assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
  2799. assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
  2800. assert!(matches!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
  2801. }
  2802. #[async_std::test]
  2803. async fn test_add_then_remove_meseta() {
  2804. let mut entity_gateway = InMemoryGateway::default();
  2805. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2806. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2807. entity_gateway.set_character_meseta(&char1.id, Meseta(2323)).await.unwrap();
  2808. let mut ship = standard_ship(entity_gateway.clone());
  2809. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2810. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2811. join_lobby(&mut ship, ClientId(1)).await;
  2812. join_lobby(&mut ship, ClientId(2)).await;
  2813. create_room(&mut ship, ClientId(1), "room", "").await;
  2814. join_room(&mut ship, ClientId(2), 0).await;
  2815. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2816. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2817. client: 1,
  2818. target: 0,
  2819. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 23)
  2820. })))).await.unwrap();
  2821. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2822. client: 1,
  2823. target: 0,
  2824. trade: TradeRequestCommand::RemoveItem(0xFFFFFF01, 5)
  2825. })))).await.unwrap();
  2826. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2827. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2828. let titems = TradeItemBuilder::default()
  2829. .meseta(18)
  2830. .build();
  2831. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2832. trade_target: 1,
  2833. unknown2: 0,
  2834. count: 1,
  2835. items: titems,
  2836. })).await.unwrap();
  2837. assert_eq!(ack.len(), 0);
  2838. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2839. trade_target: 0,
  2840. unknown2: 0,
  2841. count: 0,
  2842. items: Default::default(),
  2843. })).await.unwrap();
  2844. assert_eq!(ack.len(), 2);
  2845. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2846. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2847. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2848. })).await.unwrap();
  2849. assert_eq!(ack.len(), 0);
  2850. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2851. })).await.unwrap();
  2852. assert_eq!(ack.len(), 5);
  2853. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2854. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2855. ..
  2856. }))));
  2857. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2858. msg: GameMessage::CreateItem(CreateItem {..}),
  2859. ..
  2860. }))));
  2861. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2862. msg: GameMessage::CreateItem(CreateItem {..}),
  2863. ..
  2864. }))));
  2865. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2866. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2867. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2868. assert_eq!(c1_meseta, Meseta(2305));
  2869. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2870. assert_eq!(c2_meseta, Meseta(18));
  2871. }
  2872. #[async_std::test]
  2873. async fn test_items_to_trade_data_does_not_match() {
  2874. let mut entity_gateway = InMemoryGateway::default();
  2875. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2876. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2877. let mut p1_inv = Vec::new();
  2878. p1_inv.push(entity_gateway.create_item(
  2879. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  2880. .as_new()
  2881. ).await.unwrap());
  2882. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2883. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2884. let mut ship = standard_ship(entity_gateway.clone());
  2885. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2886. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2887. join_lobby(&mut ship, ClientId(1)).await;
  2888. join_lobby(&mut ship, ClientId(2)).await;
  2889. create_room(&mut ship, ClientId(1), "room", "").await;
  2890. join_room(&mut ship, ClientId(2), 0).await;
  2891. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2892. assert_eq!(p1_items.items.len(), 1);
  2893. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2894. assert_eq!(p2_items.items.len(), 0);
  2895. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2896. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2897. client: 1,
  2898. target: 0,
  2899. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2900. })))).await.unwrap();
  2901. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2902. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2903. let new_item = item::InventoryItemEntity::Individual(
  2904. ItemEntity {
  2905. id: p1_items.items[0].with_individual(|i| i.id).unwrap(),
  2906. item: item::ItemDetail::Weapon(
  2907. item::weapon::Weapon {
  2908. weapon: item::weapon::WeaponType::Handgun,
  2909. grind: 2,
  2910. special: None,
  2911. attrs: [None, None, None],
  2912. tekked: true,
  2913. }
  2914. )});
  2915. let titems = TradeItemBuilder::default()
  2916. .individual(&new_item, 0x10000)
  2917. .build();
  2918. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2919. trade_target: 1,
  2920. unknown2: 0,
  2921. count: 1,
  2922. items: titems,
  2923. })).await.unwrap();
  2924. assert_eq!(ack.len(), 2);
  2925. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2926. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2927. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2928. assert_eq!(p1_items.items.len(), 1);
  2929. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2930. assert_eq!(p2_items.items.len(), 0);
  2931. }
  2932. #[async_std::test]
  2933. async fn test_items_to_trade_id_does_not_match() {
  2934. let mut entity_gateway = InMemoryGateway::default();
  2935. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2936. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2937. let mut p1_inv = Vec::new();
  2938. p1_inv.push(entity_gateway.create_item(
  2939. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  2940. .as_new()
  2941. ).await.unwrap());
  2942. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2943. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2944. let mut ship = standard_ship(entity_gateway.clone());
  2945. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2946. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2947. join_lobby(&mut ship, ClientId(1)).await;
  2948. join_lobby(&mut ship, ClientId(2)).await;
  2949. create_room(&mut ship, ClientId(1), "room", "").await;
  2950. join_room(&mut ship, ClientId(2), 0).await;
  2951. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2952. assert_eq!(p1_items.items.len(), 1);
  2953. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2954. assert_eq!(p2_items.items.len(), 0);
  2955. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2956. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2957. client: 1,
  2958. target: 0,
  2959. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2960. })))).await.unwrap();
  2961. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2962. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2963. let titems = TradeItemBuilder::default()
  2964. .individual(&p1_items.items[0], 0x10001)
  2965. .build();
  2966. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2967. trade_target: 1,
  2968. unknown2: 0,
  2969. count: 1,
  2970. items: titems,
  2971. })).await.unwrap();
  2972. assert_eq!(ack.len(), 2);
  2973. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2974. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2975. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2976. assert_eq!(p1_items.items.len(), 1);
  2977. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2978. assert_eq!(p2_items.items.len(), 0);
  2979. }
  2980. #[async_std::test]
  2981. async fn test_stack_is_same_amount_in_request_and_items_to_trade() {
  2982. let mut entity_gateway = InMemoryGateway::default();
  2983. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  2984. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  2985. let p1_stack = futures::future::join_all((0..2).map(|_| {
  2986. let mut entity_gateway = entity_gateway.clone();
  2987. async move {
  2988. entity_gateway.create_item(
  2989. ItemBuilder::tool(item::tool::ToolType::Monomate)
  2990. .as_new()
  2991. ).await
  2992. }}))
  2993. .await
  2994. .into_iter()
  2995. .collect::<Result<Vec<ItemEntity>,_>>()
  2996. .unwrap();
  2997. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  2998. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2999. let mut ship = standard_ship(entity_gateway.clone());
  3000. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3001. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3002. join_lobby(&mut ship, ClientId(1)).await;
  3003. join_lobby(&mut ship, ClientId(2)).await;
  3004. create_room(&mut ship, ClientId(1), "room", "").await;
  3005. join_room(&mut ship, ClientId(2), 0).await;
  3006. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3007. assert_eq!(p1_items.items.len(), 1);
  3008. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3009. assert_eq!(p2_items.items.len(), 0);
  3010. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3011. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3012. client: 1,
  3013. target: 0,
  3014. trade: TradeRequestCommand::AddItem(0x10000, 2)
  3015. })))).await.unwrap();
  3016. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3017. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3018. let titems = TradeItemBuilder::default()
  3019. .stacked(&p1_items.items[0], 0x10000, 1)
  3020. .build();
  3021. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3022. trade_target: 1,
  3023. unknown2: 0,
  3024. count: 1,
  3025. items: titems,
  3026. })).await.unwrap();
  3027. assert_eq!(ack.len(), 2);
  3028. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3029. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3030. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3031. assert_eq!(p1_items.items.len(), 1);
  3032. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3033. assert_eq!(p2_items.items.len(), 0);
  3034. }
  3035. #[async_std::test]
  3036. async fn test_stack_is_same_amount_in_request_and_items_to_trade2() {
  3037. let mut entity_gateway = InMemoryGateway::default();
  3038. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  3039. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  3040. let p1_stack = futures::future::join_all((0..2).map(|_| {
  3041. let mut entity_gateway = entity_gateway.clone();
  3042. async move {
  3043. entity_gateway.create_item(
  3044. ItemBuilder::tool(item::tool::ToolType::Monomate)
  3045. .as_new()
  3046. ).await
  3047. }}))
  3048. .await
  3049. .into_iter()
  3050. .collect::<Result<Vec<ItemEntity>,_>>()
  3051. .unwrap();
  3052. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  3053. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3054. let mut ship = standard_ship(entity_gateway.clone());
  3055. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3056. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3057. join_lobby(&mut ship, ClientId(1)).await;
  3058. join_lobby(&mut ship, ClientId(2)).await;
  3059. create_room(&mut ship, ClientId(1), "room", "").await;
  3060. join_room(&mut ship, ClientId(2), 0).await;
  3061. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3062. assert_eq!(p1_items.items.len(), 1);
  3063. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3064. assert_eq!(p2_items.items.len(), 0);
  3065. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3066. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3067. client: 1,
  3068. target: 0,
  3069. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3070. })))).await.unwrap();
  3071. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3072. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3073. let titems = TradeItemBuilder::default()
  3074. .stacked(&p1_items.items[0], 0x10000, 2)
  3075. .build();
  3076. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3077. trade_target: 1,
  3078. unknown2: 0,
  3079. count: 1,
  3080. items: titems,
  3081. })).await.unwrap();
  3082. assert_eq!(ack.len(), 2);
  3083. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3084. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3085. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3086. assert_eq!(p1_items.items.len(), 1);
  3087. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3088. assert_eq!(p2_items.items.len(), 0);
  3089. }
  3090. #[async_std::test]
  3091. async fn test_items_to_trade_count_less_than() {
  3092. let mut entity_gateway = InMemoryGateway::default();
  3093. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  3094. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  3095. let p1_inv = vec![
  3096. entity_gateway.create_item(
  3097. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  3098. .as_new()
  3099. ).await.unwrap(),
  3100. entity_gateway.create_item(
  3101. ItemBuilder::weapon(item::weapon::WeaponType::Brand)
  3102. .as_new()
  3103. ).await.unwrap(),
  3104. entity_gateway.create_item(
  3105. ItemBuilder::weapon(item::weapon::WeaponType::Buster)
  3106. .as_new()
  3107. ).await.unwrap(),
  3108. ];
  3109. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3110. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3111. let mut ship = standard_ship(entity_gateway.clone());
  3112. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3113. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3114. join_lobby(&mut ship, ClientId(1)).await;
  3115. join_lobby(&mut ship, ClientId(2)).await;
  3116. create_room(&mut ship, ClientId(1), "room", "").await;
  3117. join_room(&mut ship, ClientId(2), 0).await;
  3118. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3119. assert_eq!(p1_items.items.len(), 3);
  3120. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3121. assert_eq!(p2_items.items.len(), 0);
  3122. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3123. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3124. client: 1,
  3125. target: 0,
  3126. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3127. })))).await.unwrap();
  3128. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3129. client: 1,
  3130. target: 0,
  3131. trade: TradeRequestCommand::AddItem(0x10001, 1)
  3132. })))).await.unwrap();
  3133. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3134. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3135. let titems = TradeItemBuilder::default()
  3136. .individual(&p1_items.items[0], 0x10000)
  3137. .individual(&p1_items.items[1], 0x10001)
  3138. .build();
  3139. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3140. trade_target: 1,
  3141. unknown2: 0,
  3142. count: 1,
  3143. items: titems,
  3144. })).await.unwrap();
  3145. assert_eq!(ack.len(), 2);
  3146. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3147. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3148. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3149. assert_eq!(p1_items.items.len(), 3);
  3150. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3151. assert_eq!(p2_items.items.len(), 0);
  3152. }
  3153. #[async_std::test]
  3154. async fn test_items_to_trade_count_greater_than() {
  3155. let mut entity_gateway = InMemoryGateway::default();
  3156. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  3157. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  3158. entity_gateway.set_character_meseta(&char1.id, Meseta(23)).await.unwrap();
  3159. let p1_inv = vec![
  3160. entity_gateway.create_item(
  3161. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  3162. .as_new()
  3163. ).await.unwrap(),
  3164. entity_gateway.create_item(
  3165. ItemBuilder::weapon(item::weapon::WeaponType::Brand)
  3166. .as_new()
  3167. ).await.unwrap(),
  3168. entity_gateway.create_item(
  3169. ItemBuilder::weapon(item::weapon::WeaponType::Buster)
  3170. .as_new()
  3171. ).await.unwrap(),
  3172. ];
  3173. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3174. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3175. let mut ship = standard_ship(entity_gateway.clone());
  3176. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3177. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3178. join_lobby(&mut ship, ClientId(1)).await;
  3179. join_lobby(&mut ship, ClientId(2)).await;
  3180. create_room(&mut ship, ClientId(1), "room", "").await;
  3181. join_room(&mut ship, ClientId(2), 0).await;
  3182. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3183. assert_eq!(p1_items.items.len(), 3);
  3184. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3185. assert_eq!(p2_items.items.len(), 0);
  3186. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3187. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3188. client: 1,
  3189. target: 0,
  3190. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3191. })))).await.unwrap();
  3192. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3193. client: 1,
  3194. target: 0,
  3195. trade: TradeRequestCommand::AddItem(0x10001, 1)
  3196. })))).await.unwrap();
  3197. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3198. client: 1,
  3199. target: 0,
  3200. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 5)
  3201. })))).await.unwrap();
  3202. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3203. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3204. let titems = TradeItemBuilder::default()
  3205. .individual(&p1_items.items[0], 0x10000)
  3206. .individual(&p1_items.items[1], 0x10001)
  3207. .meseta(5)
  3208. .build();
  3209. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3210. trade_target: 1,
  3211. unknown2: 0,
  3212. count: 4,
  3213. items: titems,
  3214. })).await.unwrap();
  3215. assert_eq!(ack.len(), 2);
  3216. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3217. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3218. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3219. assert_eq!(p1_items.items.len(), 3);
  3220. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3221. assert_eq!(p2_items.items.len(), 0);
  3222. }
  3223. #[async_std::test]
  3224. async fn test_items_to_trade_count_mismatch_with_meseta() {
  3225. let mut entity_gateway = InMemoryGateway::default();
  3226. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  3227. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  3228. let p1_inv = vec![
  3229. entity_gateway.create_item(
  3230. ItemBuilder::weapon(item::weapon::WeaponType::Saber)
  3231. .as_new()
  3232. ).await.unwrap(),
  3233. entity_gateway.create_item(
  3234. ItemBuilder::weapon(item::weapon::WeaponType::Brand)
  3235. .as_new()
  3236. ).await.unwrap(),
  3237. entity_gateway.create_item(
  3238. ItemBuilder::weapon(item::weapon::WeaponType::Buster)
  3239. .as_new()
  3240. ).await.unwrap(),
  3241. ];
  3242. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3243. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3244. let mut ship = standard_ship(entity_gateway.clone());
  3245. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3246. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3247. join_lobby(&mut ship, ClientId(1)).await;
  3248. join_lobby(&mut ship, ClientId(2)).await;
  3249. create_room(&mut ship, ClientId(1), "room", "").await;
  3250. join_room(&mut ship, ClientId(2), 0).await;
  3251. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3252. assert_eq!(p1_items.items.len(), 3);
  3253. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3254. assert_eq!(p2_items.items.len(), 0);
  3255. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3256. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3257. client: 1,
  3258. target: 0,
  3259. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3260. })))).await.unwrap();
  3261. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3262. client: 1,
  3263. target: 0,
  3264. trade: TradeRequestCommand::AddItem(0x10001, 1)
  3265. })))).await.unwrap();
  3266. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3267. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3268. let titems = TradeItemBuilder::default()
  3269. .individual(&p1_items.items[0], 0x10000)
  3270. .individual(&p1_items.items[1], 0x10001)
  3271. .build();
  3272. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3273. trade_target: 1,
  3274. unknown2: 0,
  3275. count: 3,
  3276. items: titems,
  3277. })).await.unwrap();
  3278. assert_eq!(ack.len(), 2);
  3279. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3280. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3281. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3282. assert_eq!(p1_items.items.len(), 3);
  3283. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3284. assert_eq!(p2_items.items.len(), 0);
  3285. }
  3286. #[async_std::test]
  3287. async fn test_dropping_item_after_trade() {
  3288. let mut entity_gateway = InMemoryGateway::default();
  3289. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  3290. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  3291. let mut p1_inv = Vec::new();
  3292. p1_inv.push(entity_gateway.create_item(
  3293. ItemBuilder::weapon(item::weapon::WeaponType::Handgun)
  3294. .as_new()
  3295. ).await.unwrap());
  3296. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3297. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3298. let mut ship = standard_ship(entity_gateway.clone());
  3299. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3300. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3301. join_lobby(&mut ship, ClientId(1)).await;
  3302. join_lobby(&mut ship, ClientId(2)).await;
  3303. create_room(&mut ship, ClientId(1), "room", "").await;
  3304. join_room(&mut ship, ClientId(2), 0).await;
  3305. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3306. assert_eq!(p1_items.items.len(), 1);
  3307. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3308. assert_eq!(p2_items.items.len(), 0);
  3309. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3310. ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3311. client: 1,
  3312. target: 0,
  3313. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3314. })))).await.unwrap();
  3315. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3316. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3317. let titems = TradeItemBuilder::default()
  3318. .individual(&p1_items.items[0], 0x10000)
  3319. .build();
  3320. let ack = ship.handle(ClientId(1), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3321. trade_target: 1,
  3322. unknown2: 0,
  3323. count: 1,
  3324. items: titems,
  3325. })).await.unwrap();
  3326. assert_eq!(ack.len(), 0);
  3327. let ack = ship.handle(ClientId(2), RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3328. trade_target: 0,
  3329. unknown2: 0,
  3330. count: 0,
  3331. items: Default::default(),
  3332. })).await.unwrap();
  3333. assert_eq!(ack.len(), 2);
  3334. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3335. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3336. let ack = ship.handle(ClientId(1), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3337. })).await.unwrap();
  3338. assert_eq!(ack.len(), 0);
  3339. let ack = ship.handle(ClientId(2), RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3340. })).await.unwrap();
  3341. assert_eq!(ack.len(), 5);
  3342. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  3343. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  3344. ..
  3345. }))));
  3346. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  3347. msg: GameMessage::CreateItem(CreateItem {..}),
  3348. ..
  3349. }))));
  3350. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  3351. msg: GameMessage::CreateItem(CreateItem {..}),
  3352. ..
  3353. }))));
  3354. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  3355. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  3356. let _ack = ship.handle(ClientId(2), RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  3357. client: 0,
  3358. target: 0,
  3359. unknown1: 0,
  3360. map_area: 0,
  3361. item_id: 0x810001,
  3362. x: 0.0,
  3363. y: 0.0,
  3364. z: 0.0,
  3365. })))).await.unwrap();
  3366. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3367. assert_eq!(p1_items.items.len(), 0);
  3368. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3369. assert_eq!(p2_items.items.len(), 0);
  3370. }