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.

4382 lines
176 KiB

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