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.

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