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.

4414 lines
177 KiB

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