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.

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