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.

4396 lines
177 KiB

2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 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, ShipError};
  6. use elseware::entity::item::{Meseta, ItemEntity};
  7. use elseware::ship::packet::handler::trade::TradeError;
  8. use elseware::ship::items::state::{ItemStateError, InventoryError};
  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(2), SendShipPacket::Message(Message {
  163. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  164. ..
  165. }))));
  166. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  167. msg: GameMessage::CreateItem(CreateItem {..}),
  168. ..
  169. }))));
  170. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  171. msg: GameMessage::CreateItem(CreateItem {..}),
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  250. ..
  251. }))));
  252. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  253. msg: GameMessage::CreateItem(CreateItem {..}),
  254. ..
  255. }))));
  256. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  257. msg: GameMessage::CreateItem(CreateItem {..}),
  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(2), SendShipPacket::Message(Message {
  335. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  336. ..
  337. }))));
  338. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  339. msg: GameMessage::CreateItem(CreateItem {..}),
  340. ..
  341. }))));
  342. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  343. msg: GameMessage::CreateItem(CreateItem {..}),
  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(2), SendShipPacket::Message(Message {
  423. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  424. ..
  425. }))));
  426. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  427. msg: GameMessage::CreateItem(CreateItem {..}),
  428. ..
  429. }))));
  430. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  431. msg: GameMessage::CreateItem(CreateItem {..}),
  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(2), SendShipPacket::Message(Message {
  512. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  513. ..
  514. }))));
  515. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  516. msg: GameMessage::CreateItem(CreateItem {..}),
  517. ..
  518. }))));
  519. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  520. msg: GameMessage::CreateItem(CreateItem {..}),
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  623. client: 1,
  624. item_id: 0x210000,
  625. ..
  626. }),
  627. ..
  628. }))));
  629. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  630. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  631. client: 0,
  632. item_id: 0x10000,
  633. ..
  634. }),
  635. ..
  636. }))));
  637. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  638. msg: GameMessage::CreateItem(CreateItem {
  639. client: 1,
  640. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  641. item_id: 0x810002,
  642. ..
  643. }),
  644. ..
  645. }))));
  646. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  647. msg: GameMessage::CreateItem(CreateItem {
  648. client: 1,
  649. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  650. item_id: 0x810002,
  651. ..
  652. }),
  653. ..
  654. }))));
  655. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  656. msg: GameMessage::CreateItem(CreateItem {
  657. client: 0,
  658. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  659. item_id: 0x810001,
  660. ..
  661. }),
  662. ..
  663. }))));
  664. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  665. msg: GameMessage::CreateItem(CreateItem {
  666. client: 0,
  667. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  668. item_id: 0x810001,
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  777. client: 1,
  778. item_id: 0x210000,
  779. ..
  780. }),
  781. ..
  782. }))));
  783. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  784. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  785. client: 0,
  786. item_id: 0x10000,
  787. ..
  788. }),
  789. ..
  790. }))));
  791. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  792. msg: GameMessage::CreateItem(CreateItem {
  793. client: 1,
  794. item_id: 0x810002,
  795. ..
  796. }),
  797. ..
  798. }))));
  799. assert!(matches!(ack[3], (ClientId(2), 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(1), SendShipPacket::Message(Message {
  808. msg: GameMessage::CreateItem(CreateItem {
  809. client: 0,
  810. item_id: 0x810001,
  811. ..
  812. }),
  813. ..
  814. }))));
  815. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  816. msg: GameMessage::CreateItem(CreateItem {
  817. client: 0,
  818. item_id: 0x810001,
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  929. client: 1,
  930. item_id: 0x210000,
  931. amount: 2,
  932. ..
  933. }),
  934. ..
  935. }))));
  936. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  937. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  938. client: 0,
  939. item_id: 0x10000,
  940. amount: 1,
  941. ..
  942. }),
  943. ..
  944. }))));
  945. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  946. msg: GameMessage::CreateItem(CreateItem {
  947. client: 1,
  948. item_id: 0x810002,
  949. ..
  950. }),
  951. ..
  952. }))));
  953. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  954. msg: GameMessage::CreateItem(CreateItem {
  955. client: 1,
  956. item_id: 0x810002,
  957. ..
  958. }),
  959. ..
  960. }))));
  961. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  962. msg: GameMessage::CreateItem(CreateItem {
  963. client: 0,
  964. item_id: 0x810001,
  965. ..
  966. }),
  967. ..
  968. }))));
  969. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  970. msg: GameMessage::CreateItem(CreateItem {
  971. client: 0,
  972. item_id: 0x810001,
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1087. client: 1,
  1088. item_id: 0x210000,
  1089. amount: 3,
  1090. ..
  1091. }),
  1092. ..
  1093. }))));
  1094. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  1095. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1096. client: 0,
  1097. item_id: 0x10000,
  1098. amount: 1,
  1099. ..
  1100. }),
  1101. ..
  1102. }))));
  1103. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  1104. msg: GameMessage::CreateItem(CreateItem {
  1105. client: 1,
  1106. item_id: 0x810002,
  1107. ..
  1108. }),
  1109. ..
  1110. }))));
  1111. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1112. msg: GameMessage::CreateItem(CreateItem {
  1113. client: 1,
  1114. item_id: 0x810002,
  1115. ..
  1116. }),
  1117. ..
  1118. }))));
  1119. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1120. msg: GameMessage::CreateItem(CreateItem {
  1121. client: 0,
  1122. item_id: 0x810001,
  1123. ..
  1124. }),
  1125. ..
  1126. }))));
  1127. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1128. msg: GameMessage::CreateItem(CreateItem {
  1129. client: 0,
  1130. item_id: 0x810001,
  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(2), SendShipPacket::Message(Message {
  1232. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1233. client: 0,
  1234. item_id: 0x10000,
  1235. amount: 2,
  1236. ..
  1237. }),
  1238. ..
  1239. }))));
  1240. assert!(matches!(ack[1], (ClientId(1), 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::CreateItem(CreateItem {
  1251. client: 1,
  1252. item_id: 0x810001,
  1253. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1362. client: 1,
  1363. item_id: 0x210000,
  1364. ..
  1365. }),
  1366. ..
  1367. }))));
  1368. assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
  1369. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1370. client: 0,
  1371. item_id: 0x10000,
  1372. ..
  1373. }),
  1374. ..
  1375. }))));
  1376. assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
  1377. msg: GameMessage::CreateItem(CreateItem {
  1378. client: 1,
  1379. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  1380. item_id: 0x810002,
  1381. ..
  1382. }),
  1383. ..
  1384. }))));
  1385. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1386. msg: GameMessage::CreateItem(CreateItem {
  1387. client: 1,
  1388. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  1389. item_id: 0x810002,
  1390. ..
  1391. }),
  1392. ..
  1393. }))));
  1394. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1395. msg: GameMessage::CreateItem(CreateItem {
  1396. client: 0,
  1397. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  1398. item_id: 0x810001,
  1399. ..
  1400. }),
  1401. ..
  1402. }))));
  1403. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1404. msg: GameMessage::CreateItem(CreateItem {
  1405. client: 0,
  1406. item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
  1407. item_id: 0x810001,
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1553. client: 1,
  1554. item_id: 0x210000,
  1555. ..
  1556. }),
  1557. ..
  1558. }))));
  1559. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  1560. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1561. client: 1,
  1562. item_id: 0x210001,
  1563. ..
  1564. }),
  1565. ..
  1566. }))));
  1567. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  1568. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1569. client: 0,
  1570. item_id: 0x10000,
  1571. ..
  1572. }),
  1573. ..
  1574. }))));
  1575. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1576. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1577. client: 0,
  1578. item_id: 0x10001,
  1579. ..
  1580. }),
  1581. ..
  1582. }))));
  1583. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1584. msg: GameMessage::CreateItem(CreateItem {
  1585. client: 1,
  1586. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1587. item_id: 0x810003,
  1588. ..
  1589. }),
  1590. ..
  1591. }))));
  1592. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1593. msg: GameMessage::CreateItem(CreateItem {
  1594. client: 1,
  1595. item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1596. item_id: 0x810003,
  1597. ..
  1598. }),
  1599. ..
  1600. }))));
  1601. assert!(matches!(ack[6], (ClientId(1), SendShipPacket::Message(Message {
  1602. msg: GameMessage::CreateItem(CreateItem {
  1603. client: 1,
  1604. item_data: [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1605. item_id: 0x810004,
  1606. ..
  1607. }),
  1608. ..
  1609. }))));
  1610. assert!(matches!(ack[7], (ClientId(2), SendShipPacket::Message(Message {
  1611. msg: GameMessage::CreateItem(CreateItem {
  1612. client: 1,
  1613. item_data: [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
  1614. item_id: 0x810004,
  1615. ..
  1616. }),
  1617. ..
  1618. }))));
  1619. assert!(matches!(ack[8], (ClientId(1), SendShipPacket::Message(Message {
  1620. msg: GameMessage::CreateItem(CreateItem {
  1621. client: 0,
  1622. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1623. item_id: 0x810001,
  1624. ..
  1625. }),
  1626. ..
  1627. }))));
  1628. assert!(matches!(ack[9], (ClientId(2), SendShipPacket::Message(Message {
  1629. msg: GameMessage::CreateItem(CreateItem {
  1630. client: 0,
  1631. item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1632. item_id: 0x810001,
  1633. ..
  1634. }),
  1635. ..
  1636. }))));
  1637. assert!(matches!(ack[10], (ClientId(1), SendShipPacket::Message(Message {
  1638. msg: GameMessage::CreateItem(CreateItem {
  1639. client: 0,
  1640. item_data: [0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1641. item_id: 0x810002,
  1642. ..
  1643. }),
  1644. ..
  1645. }))));
  1646. assert!(matches!(ack[11], (ClientId(2), SendShipPacket::Message(Message {
  1647. msg: GameMessage::CreateItem(CreateItem {
  1648. client: 0,
  1649. item_data: [0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
  1650. item_id: 0x810002,
  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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1805. client: 1,
  1806. item_id: 0x210000,
  1807. ..
  1808. }),
  1809. ..
  1810. }))));
  1811. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  1812. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1813. client: 1,
  1814. item_id: 0x210001,
  1815. ..
  1816. }),
  1817. ..
  1818. }))));
  1819. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  1820. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1821. client: 0,
  1822. item_id: 0x10000,
  1823. ..
  1824. }),
  1825. ..
  1826. }))));
  1827. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::Message(Message {
  1828. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
  1829. client: 0,
  1830. item_id: 0x10001,
  1831. ..
  1832. }),
  1833. ..
  1834. }))));
  1835. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::Message(Message {
  1836. msg: GameMessage::CreateItem(CreateItem {
  1837. client: 1,
  1838. item_id: 0x810003,
  1839. ..
  1840. }),
  1841. ..
  1842. }))));
  1843. assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
  1844. msg: GameMessage::CreateItem(CreateItem {
  1845. client: 1,
  1846. item_id: 0x810003,
  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: 0x810004,
  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: 0x810004,
  1863. ..
  1864. }),
  1865. ..
  1866. }))));
  1867. assert!(matches!(ack[8], (ClientId(1), SendShipPacket::Message(Message {
  1868. msg: GameMessage::CreateItem(CreateItem {
  1869. client: 0,
  1870. item_id: 0x810001,
  1871. ..
  1872. }),
  1873. ..
  1874. }))));
  1875. assert!(matches!(ack[9], (ClientId(2), SendShipPacket::Message(Message {
  1876. msg: GameMessage::CreateItem(CreateItem {
  1877. client: 0,
  1878. item_id: 0x810001,
  1879. ..
  1880. }),
  1881. ..
  1882. }))));
  1883. assert!(matches!(ack[10], (ClientId(1), SendShipPacket::Message(Message {
  1884. msg: GameMessage::CreateItem(CreateItem {
  1885. client: 0,
  1886. item_id: 0x810002,
  1887. ..
  1888. }),
  1889. ..
  1890. }))));
  1891. assert!(matches!(ack[11], (ClientId(2), SendShipPacket::Message(Message {
  1892. msg: GameMessage::CreateItem(CreateItem {
  1893. client: 0,
  1894. item_id: 0x810002,
  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. assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::InventoryFull)));
  2011. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2012. assert_eq!(p1_items.items.len(), 2);
  2013. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2014. assert_eq!(p2_items.items.len(), 30);
  2015. }
  2016. #[async_std::test]
  2017. async fn test_trade_not_enough_inventory_space_stacked() {
  2018. let mut entity_gateway = InMemoryGateway::default();
  2019. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2020. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2021. let p1_stack = futures::future::join_all((0..2).map(|_| {
  2022. let mut entity_gateway = entity_gateway.clone();
  2023. async move {
  2024. entity_gateway.create_item(
  2025. item::NewItemEntity {
  2026. item: item::ItemDetail::Tool(
  2027. item::tool::Tool {
  2028. tool: item::tool::ToolType::Monomate,
  2029. }
  2030. )
  2031. }).await
  2032. }}))
  2033. .await
  2034. .into_iter()
  2035. .collect::<Result<Vec<ItemEntity>,_>>()
  2036. .unwrap();
  2037. let p2_inv = futures::future::join_all((0..30).map(|_| {
  2038. let mut entity_gateway = entity_gateway.clone();
  2039. async move {
  2040. entity_gateway.create_item(
  2041. item::NewItemEntity {
  2042. item: item::ItemDetail::Weapon(
  2043. item::weapon::Weapon {
  2044. weapon: item::weapon::WeaponType::Handgun,
  2045. grind: 0,
  2046. special: None,
  2047. attrs: [None, None, None],
  2048. tekked: true,
  2049. kills: None,
  2050. }
  2051. ),
  2052. }
  2053. ).await
  2054. }}))
  2055. .await
  2056. .into_iter()
  2057. .collect::<Result<Vec<ItemEntity>,_>>()
  2058. .unwrap();
  2059. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  2060. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  2061. let mut ship = Box::new(ShipServerState::builder()
  2062. .gateway(entity_gateway.clone())
  2063. .build());
  2064. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2065. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2066. join_lobby(&mut ship, ClientId(1)).await;
  2067. join_lobby(&mut ship, ClientId(2)).await;
  2068. create_room(&mut ship, ClientId(1), "room", "").await;
  2069. join_room(&mut ship, ClientId(2), 0).await;
  2070. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2071. assert_eq!(p1_items.items.len(), 1);
  2072. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2073. assert_eq!(p2_items.items.len(), 30);
  2074. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2075. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2076. client: 1,
  2077. target: 0,
  2078. trade: TradeRequestCommand::AddItem(0x10000, 2)
  2079. })))).await.unwrap().for_each(drop);
  2080. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2081. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2082. let titems = TradeItemBuilder::default()
  2083. .stacked(&p1_items.items[0], 0x10000, 2)
  2084. .build();
  2085. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2086. trade_target: 1,
  2087. unknown2: 0,
  2088. count: 1,
  2089. items: titems,
  2090. })).await.unwrap().collect::<Vec<_>>();
  2091. assert_eq!(ack.len(), 0);
  2092. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2093. trade_target: 0,
  2094. unknown2: 0,
  2095. count: 0,
  2096. items: Default::default(),
  2097. })).await.unwrap().collect::<Vec<_>>();
  2098. assert_eq!(ack.len(), 2);
  2099. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2100. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2101. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2102. })).await.unwrap().collect::<Vec<_>>();
  2103. assert_eq!(ack.len(), 0);
  2104. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2105. })).await.err().unwrap();
  2106. assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::InventoryFull)));
  2107. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2108. assert_eq!(p1_items.items.len(), 1);
  2109. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2110. assert_eq!(p2_items.items.len(), 30);
  2111. }
  2112. #[async_std::test]
  2113. async fn test_trade_stack_too_big() {
  2114. let mut entity_gateway = InMemoryGateway::default();
  2115. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2116. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2117. let p1_stack = futures::future::join_all((0..8).map(|_| {
  2118. let mut entity_gateway = entity_gateway.clone();
  2119. async move {
  2120. entity_gateway.create_item(
  2121. item::NewItemEntity {
  2122. item: item::ItemDetail::Tool(
  2123. item::tool::Tool {
  2124. tool: item::tool::ToolType::Monomate,
  2125. }
  2126. )
  2127. }).await
  2128. }}))
  2129. .await
  2130. .into_iter()
  2131. .collect::<Result<Vec<ItemEntity>,_>>()
  2132. .unwrap();
  2133. let p2_stack = futures::future::join_all((0..7).map(|_| {
  2134. let mut entity_gateway = entity_gateway.clone();
  2135. async move {
  2136. entity_gateway.create_item(
  2137. item::NewItemEntity {
  2138. item: item::ItemDetail::Tool(
  2139. item::tool::Tool {
  2140. tool: item::tool::ToolType::Monomate,
  2141. }
  2142. )
  2143. }).await
  2144. }}))
  2145. .await
  2146. .into_iter()
  2147. .collect::<Result<Vec<ItemEntity>,_>>()
  2148. .unwrap();
  2149. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  2150. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
  2151. let mut ship = Box::new(ShipServerState::builder()
  2152. .gateway(entity_gateway.clone())
  2153. .build());
  2154. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2155. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2156. join_lobby(&mut ship, ClientId(1)).await;
  2157. join_lobby(&mut ship, ClientId(2)).await;
  2158. create_room(&mut ship, ClientId(1), "room", "").await;
  2159. join_room(&mut ship, ClientId(2), 0).await;
  2160. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2161. assert_eq!(p1_items.items.len(), 1);
  2162. assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 8);
  2163. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2164. assert_eq!(p2_items.items.len(), 1);
  2165. assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 7);
  2166. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2167. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2168. client: 1,
  2169. target: 0,
  2170. trade: TradeRequestCommand::AddItem(0x10000, 4)
  2171. })))).await.unwrap().for_each(drop);
  2172. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2173. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2174. let titems = TradeItemBuilder::default()
  2175. .stacked(&p1_items.items[0], 0x10000, 4)
  2176. .build();
  2177. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2178. trade_target: 1,
  2179. unknown2: 0,
  2180. count: 1,
  2181. items: titems,
  2182. })).await.unwrap().collect::<Vec<_>>();
  2183. assert_eq!(ack.len(), 0);
  2184. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2185. trade_target: 0,
  2186. unknown2: 0,
  2187. count: 0,
  2188. items: Default::default(),
  2189. })).await.unwrap().collect::<Vec<_>>();
  2190. assert_eq!(ack.len(), 2);
  2191. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2192. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2193. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2194. })).await.unwrap().collect::<Vec<_>>();
  2195. assert_eq!(ack.len(), 0);
  2196. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2197. })).await.err().unwrap();
  2198. assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::StackFull)));
  2199. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2200. assert_eq!(p1_items.items.len(), 1);
  2201. assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 8);
  2202. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2203. assert_eq!(p2_items.items.len(), 1);
  2204. assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 7);
  2205. }
  2206. #[async_std::test]
  2207. async fn test_trade_meseta() {
  2208. let mut entity_gateway = InMemoryGateway::default();
  2209. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2210. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2211. entity_gateway.set_character_meseta(&char1.id, Meseta(2323)).await.unwrap();
  2212. let mut ship = Box::new(ShipServerState::builder()
  2213. .gateway(entity_gateway.clone())
  2214. .build());
  2215. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2216. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2217. join_lobby(&mut ship, ClientId(1)).await;
  2218. join_lobby(&mut ship, ClientId(2)).await;
  2219. create_room(&mut ship, ClientId(1), "room", "").await;
  2220. join_room(&mut ship, ClientId(2), 0).await;
  2221. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2222. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2223. client: 1,
  2224. target: 0,
  2225. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 23)
  2226. })))).await.unwrap().for_each(drop);
  2227. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2228. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2229. let titems = TradeItemBuilder::default()
  2230. .meseta(23)
  2231. .build();
  2232. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2233. trade_target: 1,
  2234. unknown2: 0,
  2235. count: 1,
  2236. items: titems,
  2237. })).await.unwrap().collect::<Vec<_>>();
  2238. assert_eq!(ack.len(), 0);
  2239. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2240. trade_target: 0,
  2241. unknown2: 0,
  2242. count: 0,
  2243. items: Default::default(),
  2244. })).await.unwrap().collect::<Vec<_>>();
  2245. assert_eq!(ack.len(), 2);
  2246. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2247. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2248. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2249. })).await.unwrap().collect::<Vec<_>>();
  2250. assert_eq!(ack.len(), 0);
  2251. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2252. })).await.unwrap().collect::<Vec<_>>();
  2253. assert_eq!(ack.len(), 5);
  2254. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2255. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2256. ..
  2257. }))));
  2258. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2259. msg: GameMessage::CreateItem(CreateItem {..}),
  2260. ..
  2261. }))));
  2262. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2263. msg: GameMessage::CreateItem(CreateItem {..}),
  2264. ..
  2265. }))));
  2266. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2267. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2268. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2269. assert_eq!(c1_meseta, Meseta(2300));
  2270. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2271. assert_eq!(c2_meseta, Meseta(23));
  2272. }
  2273. #[async_std::test]
  2274. async fn test_trade_too_much_meseta() {
  2275. let mut entity_gateway = InMemoryGateway::default();
  2276. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2277. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2278. entity_gateway.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
  2279. entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
  2280. let mut ship = Box::new(ShipServerState::builder()
  2281. .gateway(entity_gateway.clone())
  2282. .build());
  2283. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2284. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2285. join_lobby(&mut ship, ClientId(1)).await;
  2286. join_lobby(&mut ship, ClientId(2)).await;
  2287. create_room(&mut ship, ClientId(1), "room", "").await;
  2288. join_room(&mut ship, ClientId(2), 0).await;
  2289. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2290. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2291. client: 1,
  2292. target: 0,
  2293. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 2000)
  2294. })))).await.unwrap().for_each(drop);
  2295. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2296. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2297. let titems = TradeItemBuilder::default()
  2298. .meseta(2000)
  2299. .build();
  2300. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2301. trade_target: 1,
  2302. unknown2: 0,
  2303. count: 1,
  2304. items: titems,
  2305. })).await.unwrap().collect::<Vec<_>>();
  2306. assert_eq!(ack.len(), 2);
  2307. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2308. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2309. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2310. assert_eq!(c1_meseta, Meseta(4000));
  2311. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2312. assert_eq!(c2_meseta, Meseta(999000));
  2313. }
  2314. #[async_std::test]
  2315. async fn test_trade_invalid_amount_of_meseta() {
  2316. let mut entity_gateway = InMemoryGateway::default();
  2317. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2318. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2319. entity_gateway.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
  2320. entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
  2321. let mut ship = Box::new(ShipServerState::builder()
  2322. .gateway(entity_gateway.clone())
  2323. .build());
  2324. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2325. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2326. join_lobby(&mut ship, ClientId(1)).await;
  2327. join_lobby(&mut ship, ClientId(2)).await;
  2328. create_room(&mut ship, ClientId(1), "room", "").await;
  2329. join_room(&mut ship, ClientId(2), 0).await;
  2330. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2331. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2332. client: 1,
  2333. target: 0,
  2334. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 5000)
  2335. })))).await.unwrap().for_each(drop);
  2336. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2337. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2338. let titems = TradeItemBuilder::default()
  2339. .meseta(5000)
  2340. .build();
  2341. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2342. trade_target: 1,
  2343. unknown2: 0,
  2344. count: 1,
  2345. items: titems,
  2346. })).await.unwrap().collect::<Vec<_>>();
  2347. assert_eq!(ack.len(), 2);
  2348. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2349. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2350. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2351. assert_eq!(c1_meseta, Meseta(4000));
  2352. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2353. assert_eq!(c2_meseta, Meseta(999000));
  2354. }
  2355. #[async_std::test]
  2356. async fn test_trade_meseta_request_and_items_dont_match() {
  2357. let mut entity_gateway = InMemoryGateway::default();
  2358. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2359. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2360. entity_gateway.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
  2361. entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
  2362. let mut ship = Box::new(ShipServerState::builder()
  2363. .gateway(entity_gateway.clone())
  2364. .build());
  2365. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2366. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2367. join_lobby(&mut ship, ClientId(1)).await;
  2368. join_lobby(&mut ship, ClientId(2)).await;
  2369. create_room(&mut ship, ClientId(1), "room", "").await;
  2370. join_room(&mut ship, ClientId(2), 0).await;
  2371. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2372. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2373. client: 1,
  2374. target: 0,
  2375. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 50)
  2376. })))).await.unwrap().for_each(drop);
  2377. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2378. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2379. let titems = TradeItemBuilder::default()
  2380. .meseta(23)
  2381. .build();
  2382. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2383. trade_target: 1,
  2384. unknown2: 0,
  2385. count: 1,
  2386. items: titems,
  2387. })).await.unwrap().collect::<Vec<_>>();
  2388. assert_eq!(ack.len(), 2);
  2389. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2390. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2391. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  2392. assert_eq!(c1_meseta, Meseta(4000));
  2393. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  2394. assert_eq!(c2_meseta, Meseta(999000));
  2395. }
  2396. #[async_std::test]
  2397. async fn test_player_declined_trade() {
  2398. let mut entity_gateway = InMemoryGateway::default();
  2399. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2400. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2401. let mut ship = Box::new(ShipServerState::builder()
  2402. .gateway(entity_gateway.clone())
  2403. .build());
  2404. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2405. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2406. join_lobby(&mut ship, ClientId(1)).await;
  2407. join_lobby(&mut ship, ClientId(2)).await;
  2408. create_room(&mut ship, ClientId(1), "room", "").await;
  2409. join_room(&mut ship, ClientId(2), 0).await;
  2410. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2411. let ack = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2412. client: 1,
  2413. target: 0,
  2414. trade: TradeRequestCommand::Cancel
  2415. })))).await.unwrap().collect::<Vec<_>>();
  2416. assert_eq!(ack.len(), 2);
  2417. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2418. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2419. }
  2420. #[async_std::test]
  2421. async fn test_back_out_of_trade_last_minute() {
  2422. let mut entity_gateway = InMemoryGateway::default();
  2423. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2424. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2425. let mut p1_inv = Vec::new();
  2426. p1_inv.push(entity_gateway.create_item(
  2427. item::NewItemEntity {
  2428. item: item::ItemDetail::Weapon(
  2429. item::weapon::Weapon {
  2430. weapon: item::weapon::WeaponType::Handgun,
  2431. grind: 0,
  2432. special: None,
  2433. attrs: [None, None, None],
  2434. tekked: true,
  2435. kills: None,
  2436. }
  2437. ),
  2438. }).await.unwrap());
  2439. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2440. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2441. let mut ship = Box::new(ShipServerState::builder()
  2442. .gateway(entity_gateway.clone())
  2443. .build());
  2444. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2445. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2446. join_lobby(&mut ship, ClientId(1)).await;
  2447. join_lobby(&mut ship, ClientId(2)).await;
  2448. create_room(&mut ship, ClientId(1), "room", "").await;
  2449. join_room(&mut ship, ClientId(2), 0).await;
  2450. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2451. assert_eq!(p1_items.items.len(), 1);
  2452. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2453. assert_eq!(p2_items.items.len(), 0);
  2454. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2455. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2456. client: 1,
  2457. target: 0,
  2458. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2459. })))).await.unwrap().for_each(drop);
  2460. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2461. let ack = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2462. client: 1,
  2463. target: 0,
  2464. trade: TradeRequestCommand::Cancel
  2465. })))).await.unwrap().collect::<Vec<_>>();
  2466. assert_eq!(ack.len(), 2);
  2467. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  2468. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  2469. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2470. assert_eq!(p1_items.items.len(), 1);
  2471. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2472. assert_eq!(p2_items.items.len(), 0);
  2473. }
  2474. #[async_std::test]
  2475. async fn test_valid_trade_when_both_inventories_are_full() {
  2476. let mut entity_gateway = InMemoryGateway::default();
  2477. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2478. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2479. let p1_inv = futures::future::join_all((0..30).map(|_| {
  2480. let mut entity_gateway = entity_gateway.clone();
  2481. async move {
  2482. entity_gateway.create_item(
  2483. item::NewItemEntity {
  2484. item: item::ItemDetail::Weapon(
  2485. item::weapon::Weapon {
  2486. weapon: item::weapon::WeaponType::Saber,
  2487. grind: 0,
  2488. special: None,
  2489. attrs: [None, None, None],
  2490. tekked: true,
  2491. kills: None,
  2492. }
  2493. ),
  2494. }
  2495. ).await
  2496. }}))
  2497. .await
  2498. .into_iter()
  2499. .collect::<Result<Vec<ItemEntity>,_>>()
  2500. .unwrap();
  2501. let p2_inv = futures::future::join_all((0..30).map(|_| {
  2502. let mut entity_gateway = entity_gateway.clone();
  2503. async move {
  2504. entity_gateway.create_item(
  2505. item::NewItemEntity {
  2506. item: item::ItemDetail::Weapon(
  2507. item::weapon::Weapon {
  2508. weapon: item::weapon::WeaponType::Handgun,
  2509. grind: 0,
  2510. special: None,
  2511. attrs: [None, None, None],
  2512. tekked: true,
  2513. kills: None,
  2514. }
  2515. ),
  2516. }
  2517. ).await
  2518. }}))
  2519. .await
  2520. .into_iter()
  2521. .collect::<Result<Vec<ItemEntity>,_>>()
  2522. .unwrap();
  2523. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2524. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  2525. let mut ship = Box::new(ShipServerState::builder()
  2526. .gateway(entity_gateway.clone())
  2527. .build());
  2528. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2529. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2530. join_lobby(&mut ship, ClientId(1)).await;
  2531. join_lobby(&mut ship, ClientId(2)).await;
  2532. create_room(&mut ship, ClientId(1), "room", "").await;
  2533. join_room(&mut ship, ClientId(2), 0).await;
  2534. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2535. assert_eq!(p1_items.items.len(), 30);
  2536. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2537. assert_eq!(p2_items.items.len(), 30);
  2538. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2539. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2540. client: 1,
  2541. target: 0,
  2542. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2543. })))).await.unwrap().for_each(drop);
  2544. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2545. client: 1,
  2546. target: 0,
  2547. trade: TradeRequestCommand::AddItem(0x10001, 1)
  2548. })))).await.unwrap().for_each(drop);
  2549. ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2550. client: 0,
  2551. target: 0,
  2552. trade: TradeRequestCommand::AddItem(0x210000, 1)
  2553. })))).await.unwrap().for_each(drop);
  2554. ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2555. client: 0,
  2556. target: 0,
  2557. trade: TradeRequestCommand::AddItem(0x210001, 1)
  2558. })))).await.unwrap().for_each(drop);
  2559. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2560. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2561. let titems = TradeItemBuilder::default()
  2562. .individual(&p1_items.items[0], 0x10000)
  2563. .individual(&p1_items.items[1], 0x10001)
  2564. .build();
  2565. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2566. trade_target: 1,
  2567. unknown2: 0,
  2568. count: 2,
  2569. items: titems,
  2570. })).await.unwrap().collect::<Vec<_>>();
  2571. assert_eq!(ack.len(), 0);
  2572. let titems = TradeItemBuilder::default()
  2573. .individual(&p2_items.items[0], 0x210000)
  2574. .individual(&p2_items.items[1], 0x210001)
  2575. .build();
  2576. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2577. trade_target: 0,
  2578. unknown2: 0,
  2579. count: 2,
  2580. items: titems,
  2581. })).await.unwrap().collect::<Vec<_>>();
  2582. assert_eq!(ack.len(), 2);
  2583. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2584. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2585. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2586. })).await.unwrap().collect::<Vec<_>>();
  2587. assert_eq!(ack.len(), 0);
  2588. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2589. })).await.unwrap().collect::<Vec<_>>();
  2590. assert_eq!(ack.len(), 14);
  2591. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2592. assert_eq!(p1_items.items.len(), 30);
  2593. 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);
  2594. 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);
  2595. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2596. assert_eq!(p2_items.items.len(), 30);
  2597. 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);
  2598. 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);
  2599. }
  2600. #[async_std::test]
  2601. async fn test_invalid_trade_when_both_inventories_are_full() {
  2602. let mut entity_gateway = InMemoryGateway::default();
  2603. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2604. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2605. let p1_inv = futures::future::join_all((0..30).map(|_| {
  2606. let mut entity_gateway = entity_gateway.clone();
  2607. async move {
  2608. entity_gateway.create_item(
  2609. item::NewItemEntity {
  2610. item: item::ItemDetail::Weapon(
  2611. item::weapon::Weapon {
  2612. weapon: item::weapon::WeaponType::Saber,
  2613. grind: 0,
  2614. special: None,
  2615. attrs: [None, None, None],
  2616. tekked: true,
  2617. kills: None,
  2618. }
  2619. ),
  2620. }
  2621. ).await
  2622. }}))
  2623. .await
  2624. .into_iter()
  2625. .collect::<Result<Vec<ItemEntity>,_>>()
  2626. .unwrap();
  2627. let p2_inv = futures::future::join_all((0..30).map(|_| {
  2628. let mut entity_gateway = entity_gateway.clone();
  2629. async move {
  2630. entity_gateway.create_item(
  2631. item::NewItemEntity {
  2632. item: item::ItemDetail::Weapon(
  2633. item::weapon::Weapon {
  2634. weapon: item::weapon::WeaponType::Handgun,
  2635. grind: 0,
  2636. special: None,
  2637. attrs: [None, None, None],
  2638. tekked: true,
  2639. kills: None,
  2640. }
  2641. ),
  2642. }
  2643. ).await
  2644. }}))
  2645. .await
  2646. .into_iter()
  2647. .collect::<Result<Vec<ItemEntity>,_>>()
  2648. .unwrap();
  2649. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2650. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  2651. let mut ship = Box::new(ShipServerState::builder()
  2652. .gateway(entity_gateway.clone())
  2653. .build());
  2654. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2655. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2656. join_lobby(&mut ship, ClientId(1)).await;
  2657. join_lobby(&mut ship, ClientId(2)).await;
  2658. create_room(&mut ship, ClientId(1), "room", "").await;
  2659. join_room(&mut ship, ClientId(2), 0).await;
  2660. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2661. assert_eq!(p1_items.items.len(), 30);
  2662. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2663. assert_eq!(p2_items.items.len(), 30);
  2664. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2665. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2666. client: 1,
  2667. target: 0,
  2668. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2669. })))).await.unwrap().for_each(drop);
  2670. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2671. client: 1,
  2672. target: 0,
  2673. trade: TradeRequestCommand::AddItem(0x10001, 1)
  2674. })))).await.unwrap().for_each(drop);
  2675. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2676. client: 1,
  2677. target: 0,
  2678. trade: TradeRequestCommand::AddItem(0x10002, 1)
  2679. })))).await.unwrap().for_each(drop);
  2680. ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2681. client: 0,
  2682. target: 0,
  2683. trade: TradeRequestCommand::AddItem(0x210000, 1)
  2684. })))).await.unwrap().for_each(drop);
  2685. ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2686. client: 0,
  2687. target: 0,
  2688. trade: TradeRequestCommand::AddItem(0x210001, 1)
  2689. })))).await.unwrap().for_each(drop);
  2690. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2691. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2692. let titems = TradeItemBuilder::default()
  2693. .individual(&p1_items.items[0], 0x10000)
  2694. .individual(&p1_items.items[1], 0x10001)
  2695. .individual(&p1_items.items[1], 0x10002)
  2696. .build();
  2697. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2698. trade_target: 1,
  2699. unknown2: 0,
  2700. count: 3,
  2701. items: titems,
  2702. })).await.unwrap().collect::<Vec<_>>();
  2703. assert_eq!(ack.len(), 0);
  2704. let titems = TradeItemBuilder::default()
  2705. .individual(&p2_items.items[0], 0x210000)
  2706. .individual(&p2_items.items[1], 0x210001)
  2707. .build();
  2708. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2709. trade_target: 0,
  2710. unknown2: 0,
  2711. count: 2,
  2712. items: titems,
  2713. })).await.unwrap().collect::<Vec<_>>();
  2714. assert_eq!(ack.len(), 2);
  2715. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2716. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2717. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2718. })).await.unwrap().collect::<Vec<_>>();
  2719. assert_eq!(ack.len(), 0);
  2720. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2721. })).await.err().unwrap();
  2722. assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::InventoryFull)));
  2723. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2724. assert_eq!(p1_items.items.len(), 30);
  2725. 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);
  2726. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2727. assert_eq!(p2_items.items.len(), 30);
  2728. 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);
  2729. }
  2730. #[async_std::test]
  2731. async fn test_client_tries_to_start_two_trades() {
  2732. let mut entity_gateway = InMemoryGateway::default();
  2733. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2734. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2735. let (_user2, _char3) = new_user_character(&mut entity_gateway, "a3", "a", 1).await;
  2736. let mut ship = Box::new(ShipServerState::builder()
  2737. .gateway(entity_gateway.clone())
  2738. .build());
  2739. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2740. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2741. log_in_char(&mut ship, ClientId(3), "a3", "a").await;
  2742. join_lobby(&mut ship, ClientId(1)).await;
  2743. join_lobby(&mut ship, ClientId(2)).await;
  2744. join_lobby(&mut ship, ClientId(3)).await;
  2745. create_room(&mut ship, ClientId(1), "room", "").await;
  2746. join_room(&mut ship, ClientId(2), 0).await;
  2747. join_room(&mut ship, ClientId(3), 0).await;
  2748. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2749. let ack = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2750. client: 0,
  2751. target: 0,
  2752. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
  2753. })))).await.err().unwrap();
  2754. assert!(matches!(ack.downcast::<ShipError>().unwrap(), ShipError::TradeError(TradeError::ClientAlreadyInTrade)));
  2755. }
  2756. #[async_std::test]
  2757. async fn test_client_tries_trading_with_client_already_trading() {
  2758. let mut entity_gateway = InMemoryGateway::default();
  2759. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2760. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2761. let (_user2, _char3) = new_user_character(&mut entity_gateway, "a3", "a", 1).await;
  2762. let mut ship = Box::new(ShipServerState::builder()
  2763. .gateway(entity_gateway.clone())
  2764. .build());
  2765. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2766. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2767. log_in_char(&mut ship, ClientId(3), "a3", "a").await;
  2768. join_lobby(&mut ship, ClientId(1)).await;
  2769. join_lobby(&mut ship, ClientId(2)).await;
  2770. join_lobby(&mut ship, ClientId(3)).await;
  2771. create_room(&mut ship, ClientId(1), "room", "").await;
  2772. join_room(&mut ship, ClientId(2), 0).await;
  2773. join_room(&mut ship, ClientId(3), 0).await;
  2774. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2775. let ack = ship.handle(ClientId(3), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
  2776. client: 2,
  2777. target: 0,
  2778. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
  2779. })))).await.err().unwrap();
  2780. assert!(matches!(ack.downcast::<ShipError>().unwrap(), ShipError::TradeError(TradeError::OtherAlreadyInTrade)));
  2781. let ack = ship.handle(ClientId(3), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2782. client: 2,
  2783. target: 0,
  2784. trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 1)
  2785. })))).await.err().unwrap();
  2786. assert!(matches!(ack.downcast::<ShipError>().unwrap(), ShipError::TradeError(TradeError::OtherAlreadyInTrade)));
  2787. }
  2788. #[async_std::test]
  2789. async fn test_add_then_remove_individual_item() {
  2790. let mut entity_gateway = InMemoryGateway::default();
  2791. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2792. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2793. let mut p1_inv = Vec::new();
  2794. for _ in 0..2 {
  2795. p1_inv.push(entity_gateway.create_item(
  2796. item::NewItemEntity {
  2797. item: item::ItemDetail::Weapon(
  2798. item::weapon::Weapon {
  2799. weapon: item::weapon::WeaponType::Handgun,
  2800. grind: 0,
  2801. special: None,
  2802. attrs: [None, None, None],
  2803. tekked: true,
  2804. kills: None,
  2805. }
  2806. ),
  2807. }).await.unwrap());
  2808. }
  2809. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  2810. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2811. let mut ship = Box::new(ShipServerState::builder()
  2812. .gateway(entity_gateway.clone())
  2813. .build());
  2814. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2815. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2816. join_lobby(&mut ship, ClientId(1)).await;
  2817. join_lobby(&mut ship, ClientId(2)).await;
  2818. create_room(&mut ship, ClientId(1), "room", "").await;
  2819. join_room(&mut ship, ClientId(2), 0).await;
  2820. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2821. assert_eq!(p1_items.items.len(), 2);
  2822. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2823. assert_eq!(p2_items.items.len(), 0);
  2824. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2825. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2826. client: 1,
  2827. target: 0,
  2828. trade: TradeRequestCommand::AddItem(0x10000, 1)
  2829. })))).await.unwrap().for_each(drop);
  2830. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2831. client: 1,
  2832. target: 0,
  2833. trade: TradeRequestCommand::AddItem(0x10001, 1)
  2834. })))).await.unwrap().for_each(drop);
  2835. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2836. client: 1,
  2837. target: 0,
  2838. trade: TradeRequestCommand::RemoveItem(0x10000, 1)
  2839. })))).await.unwrap().for_each(drop);
  2840. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2841. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2842. let titems = TradeItemBuilder::default()
  2843. .individual(&p1_items.items[1], 0x10001)
  2844. .build();
  2845. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2846. trade_target: 1,
  2847. unknown2: 0,
  2848. count: 1,
  2849. items: titems,
  2850. })).await.unwrap().collect::<Vec<_>>();
  2851. assert_eq!(ack.len(), 0);
  2852. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2853. trade_target: 0,
  2854. unknown2: 0,
  2855. count: 0,
  2856. items: Default::default(),
  2857. })).await.unwrap().collect::<Vec<_>>();
  2858. assert_eq!(ack.len(), 2);
  2859. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2860. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2861. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2862. })).await.unwrap().collect::<Vec<_>>();
  2863. assert_eq!(ack.len(), 0);
  2864. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2865. })).await.unwrap().collect::<Vec<_>>();
  2866. assert_eq!(ack.len(), 5);
  2867. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2868. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2869. ..
  2870. }))));
  2871. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2872. msg: GameMessage::CreateItem(CreateItem {..}),
  2873. ..
  2874. }))));
  2875. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2876. msg: GameMessage::CreateItem(CreateItem {..}),
  2877. ..
  2878. }))));
  2879. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2880. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2881. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2882. assert_eq!(p1_items.items.len(), 1);
  2883. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2884. assert_eq!(p2_items.items.len(), 1);
  2885. }
  2886. #[async_std::test]
  2887. async fn test_add_then_remove_stacked_item() {
  2888. let mut entity_gateway = InMemoryGateway::default();
  2889. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  2890. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  2891. let p1_stack1 = futures::future::join_all((0..2).map(|_| {
  2892. let mut entity_gateway = entity_gateway.clone();
  2893. async move {
  2894. entity_gateway.create_item(
  2895. item::NewItemEntity {
  2896. item: item::ItemDetail::Tool(
  2897. item::tool::Tool {
  2898. tool: item::tool::ToolType::Monomate,
  2899. }
  2900. )
  2901. }).await
  2902. }}))
  2903. .await
  2904. .into_iter()
  2905. .collect::<Result<Vec<ItemEntity>,_>>()
  2906. .unwrap();
  2907. let p1_stack2 = futures::future::join_all((0..2).map(|_| {
  2908. let mut entity_gateway = entity_gateway.clone();
  2909. async move {
  2910. entity_gateway.create_item(
  2911. item::NewItemEntity {
  2912. item: item::ItemDetail::Tool(
  2913. item::tool::Tool {
  2914. tool: item::tool::ToolType::Monofluid,
  2915. }
  2916. )
  2917. }).await
  2918. }}))
  2919. .await
  2920. .into_iter()
  2921. .collect::<Result<Vec<ItemEntity>,_>>()
  2922. .unwrap();
  2923. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
  2924. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  2925. let mut ship = Box::new(ShipServerState::builder()
  2926. .gateway(entity_gateway.clone())
  2927. .build());
  2928. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  2929. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  2930. join_lobby(&mut ship, ClientId(1)).await;
  2931. join_lobby(&mut ship, ClientId(2)).await;
  2932. create_room(&mut ship, ClientId(1), "room", "").await;
  2933. join_room(&mut ship, ClientId(2), 0).await;
  2934. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2935. assert_eq!(p1_items.items.len(), 2);
  2936. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  2937. assert_eq!(p2_items.items.len(), 0);
  2938. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2939. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2940. client: 1,
  2941. target: 0,
  2942. trade: TradeRequestCommand::AddItem(0x10000, 2)
  2943. })))).await.unwrap().for_each(drop);
  2944. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2945. client: 1,
  2946. target: 0,
  2947. trade: TradeRequestCommand::AddItem(0x10001, 2)
  2948. })))).await.unwrap().for_each(drop);
  2949. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  2950. client: 1,
  2951. target: 0,
  2952. trade: TradeRequestCommand::RemoveItem(0x10000, 2)
  2953. })))).await.unwrap().for_each(drop);
  2954. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2955. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  2956. let titems = TradeItemBuilder::default()
  2957. .stacked(&p1_items.items[1], 0x10001, 2)
  2958. .build();
  2959. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2960. trade_target: 1,
  2961. unknown2: 0,
  2962. count: 1,
  2963. items: titems,
  2964. })).await.unwrap().collect::<Vec<_>>();
  2965. assert_eq!(ack.len(), 0);
  2966. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  2967. trade_target: 0,
  2968. unknown2: 0,
  2969. count: 0,
  2970. items: Default::default(),
  2971. })).await.unwrap().collect::<Vec<_>>();
  2972. assert_eq!(ack.len(), 2);
  2973. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2974. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  2975. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2976. })).await.unwrap().collect::<Vec<_>>();
  2977. assert_eq!(ack.len(), 0);
  2978. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  2979. })).await.unwrap().collect::<Vec<_>>();
  2980. assert_eq!(ack.len(), 5);
  2981. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  2982. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  2983. ..
  2984. }))));
  2985. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  2986. msg: GameMessage::CreateItem(CreateItem {..}),
  2987. ..
  2988. }))));
  2989. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  2990. msg: GameMessage::CreateItem(CreateItem {..}),
  2991. ..
  2992. }))));
  2993. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  2994. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  2995. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  2996. assert_eq!(p1_items.items.len(), 1);
  2997. 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, ..}), ..}));
  2998. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  2999. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3000. assert_eq!(p2_items.items.len(), 1);
  3001. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
  3002. 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, ..}), ..}));
  3003. }
  3004. #[async_std::test]
  3005. async fn test_add_then_remove_partial_stack() {
  3006. let mut entity_gateway = InMemoryGateway::default();
  3007. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3008. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3009. let p1_stack1 = futures::future::join_all((0..2).map(|_| {
  3010. let mut entity_gateway = entity_gateway.clone();
  3011. async move {
  3012. entity_gateway.create_item(
  3013. item::NewItemEntity {
  3014. item: item::ItemDetail::Tool(
  3015. item::tool::Tool {
  3016. tool: item::tool::ToolType::Monomate,
  3017. }
  3018. )
  3019. }).await
  3020. }}))
  3021. .await
  3022. .into_iter()
  3023. .collect::<Result<Vec<ItemEntity>,_>>()
  3024. .unwrap();
  3025. let p1_stack2 = futures::future::join_all((0..2).map(|_| {
  3026. let mut entity_gateway = entity_gateway.clone();
  3027. async move {
  3028. entity_gateway.create_item(
  3029. item::NewItemEntity {
  3030. item: item::ItemDetail::Tool(
  3031. item::tool::Tool {
  3032. tool: item::tool::ToolType::Monofluid,
  3033. }
  3034. )
  3035. }).await
  3036. }}))
  3037. .await
  3038. .into_iter()
  3039. .collect::<Result<Vec<ItemEntity>,_>>()
  3040. .unwrap();
  3041. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
  3042. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3043. let mut ship = Box::new(ShipServerState::builder()
  3044. .gateway(entity_gateway.clone())
  3045. .build());
  3046. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3047. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3048. join_lobby(&mut ship, ClientId(1)).await;
  3049. join_lobby(&mut ship, ClientId(2)).await;
  3050. create_room(&mut ship, ClientId(1), "room", "").await;
  3051. join_room(&mut ship, ClientId(2), 0).await;
  3052. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3053. assert_eq!(p1_items.items.len(), 2);
  3054. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3055. assert_eq!(p2_items.items.len(), 0);
  3056. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3057. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3058. client: 1,
  3059. target: 0,
  3060. trade: TradeRequestCommand::AddItem(0x10000, 2)
  3061. })))).await.unwrap().for_each(drop);
  3062. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3063. client: 1,
  3064. target: 0,
  3065. trade: TradeRequestCommand::AddItem(0x10001, 2)
  3066. })))).await.unwrap().for_each(drop);
  3067. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3068. client: 1,
  3069. target: 0,
  3070. trade: TradeRequestCommand::RemoveItem(0x10000, 1)
  3071. })))).await.unwrap().for_each(drop);
  3072. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3073. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3074. let titems = TradeItemBuilder::default()
  3075. .stacked(&p1_items.items[0], 0x10000, 1)
  3076. .stacked(&p1_items.items[1], 0x10001, 2)
  3077. .build();
  3078. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3079. trade_target: 1,
  3080. unknown2: 0,
  3081. count: 2,
  3082. items: titems,
  3083. })).await.unwrap().collect::<Vec<_>>();
  3084. assert_eq!(ack.len(), 0);
  3085. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3086. trade_target: 0,
  3087. unknown2: 0,
  3088. count: 0,
  3089. items: Default::default(),
  3090. })).await.unwrap().collect::<Vec<_>>();
  3091. assert_eq!(ack.len(), 2);
  3092. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3093. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3094. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3095. })).await.unwrap().collect::<Vec<_>>();
  3096. assert_eq!(ack.len(), 0);
  3097. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3098. })).await.unwrap().collect::<Vec<_>>();
  3099. assert_eq!(ack.len(), 8);
  3100. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3101. assert_eq!(p1_items.items.len(), 1);
  3102. assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  3103. 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, ..}), ..}));
  3104. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3105. assert_eq!(p2_items.items.len(), 2);
  3106. assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
  3107. assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
  3108. 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, ..}), ..}));
  3109. 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, ..}), ..}));
  3110. }
  3111. #[async_std::test]
  3112. async fn test_add_then_remove_meseta() {
  3113. let mut entity_gateway = InMemoryGateway::default();
  3114. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3115. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3116. entity_gateway.set_character_meseta(&char1.id, Meseta(2323)).await.unwrap();
  3117. let mut ship = Box::new(ShipServerState::builder()
  3118. .gateway(entity_gateway.clone())
  3119. .build());
  3120. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3121. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3122. join_lobby(&mut ship, ClientId(1)).await;
  3123. join_lobby(&mut ship, ClientId(2)).await;
  3124. create_room(&mut ship, ClientId(1), "room", "").await;
  3125. join_room(&mut ship, ClientId(2), 0).await;
  3126. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3127. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3128. client: 1,
  3129. target: 0,
  3130. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 23)
  3131. })))).await.unwrap().for_each(drop);
  3132. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3133. client: 1,
  3134. target: 0,
  3135. trade: TradeRequestCommand::RemoveItem(0xFFFFFF01, 5)
  3136. })))).await.unwrap().for_each(drop);
  3137. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3138. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3139. let titems = TradeItemBuilder::default()
  3140. .meseta(18)
  3141. .build();
  3142. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3143. trade_target: 1,
  3144. unknown2: 0,
  3145. count: 1,
  3146. items: titems,
  3147. })).await.unwrap().collect::<Vec<_>>();
  3148. assert_eq!(ack.len(), 0);
  3149. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3150. trade_target: 0,
  3151. unknown2: 0,
  3152. count: 0,
  3153. items: Default::default(),
  3154. })).await.unwrap().collect::<Vec<_>>();
  3155. assert_eq!(ack.len(), 2);
  3156. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3157. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3158. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3159. })).await.unwrap().collect::<Vec<_>>();
  3160. assert_eq!(ack.len(), 0);
  3161. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3162. })).await.unwrap().collect::<Vec<_>>();
  3163. assert_eq!(ack.len(), 5);
  3164. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  3165. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  3166. ..
  3167. }))));
  3168. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  3169. msg: GameMessage::CreateItem(CreateItem {..}),
  3170. ..
  3171. }))));
  3172. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  3173. msg: GameMessage::CreateItem(CreateItem {..}),
  3174. ..
  3175. }))));
  3176. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  3177. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  3178. let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
  3179. assert_eq!(c1_meseta, Meseta(2305));
  3180. let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
  3181. assert_eq!(c2_meseta, Meseta(18));
  3182. }
  3183. #[async_std::test]
  3184. async fn test_items_to_trade_data_does_not_match() {
  3185. let mut entity_gateway = InMemoryGateway::default();
  3186. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3187. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3188. let mut p1_inv = Vec::new();
  3189. p1_inv.push(entity_gateway.create_item(
  3190. item::NewItemEntity {
  3191. item: item::ItemDetail::Weapon(
  3192. item::weapon::Weapon {
  3193. weapon: item::weapon::WeaponType::Handgun,
  3194. grind: 0,
  3195. special: None,
  3196. attrs: [None, None, None],
  3197. tekked: true,
  3198. kills: None,
  3199. }
  3200. ),
  3201. }).await.unwrap());
  3202. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3203. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3204. let mut ship = Box::new(ShipServerState::builder()
  3205. .gateway(entity_gateway.clone())
  3206. .build());
  3207. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3208. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3209. join_lobby(&mut ship, ClientId(1)).await;
  3210. join_lobby(&mut ship, ClientId(2)).await;
  3211. create_room(&mut ship, ClientId(1), "room", "").await;
  3212. join_room(&mut ship, ClientId(2), 0).await;
  3213. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3214. assert_eq!(p1_items.items.len(), 1);
  3215. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3216. assert_eq!(p2_items.items.len(), 0);
  3217. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3218. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3219. client: 1,
  3220. target: 0,
  3221. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3222. })))).await.unwrap().for_each(drop);
  3223. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3224. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3225. let new_item = item::InventoryItemEntity::Individual(
  3226. ItemEntity {
  3227. id: p1_items.items[0].with_individual(|i| i.id).unwrap(),
  3228. item: item::ItemDetail::Weapon(
  3229. item::weapon::Weapon {
  3230. weapon: item::weapon::WeaponType::Handgun,
  3231. grind: 2,
  3232. special: None,
  3233. attrs: [None, None, None],
  3234. tekked: true,
  3235. kills: None,
  3236. }
  3237. )});
  3238. let titems = TradeItemBuilder::default()
  3239. .individual(&new_item, 0x10000)
  3240. .build();
  3241. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3242. trade_target: 1,
  3243. unknown2: 0,
  3244. count: 1,
  3245. items: titems,
  3246. })).await.unwrap().collect::<Vec<_>>();
  3247. assert_eq!(ack.len(), 2);
  3248. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3249. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3250. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3251. assert_eq!(p1_items.items.len(), 1);
  3252. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3253. assert_eq!(p2_items.items.len(), 0);
  3254. }
  3255. #[async_std::test]
  3256. async fn test_items_to_trade_id_does_not_match() {
  3257. let mut entity_gateway = InMemoryGateway::default();
  3258. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3259. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3260. let mut p1_inv = Vec::new();
  3261. p1_inv.push(entity_gateway.create_item(
  3262. item::NewItemEntity {
  3263. item: item::ItemDetail::Weapon(
  3264. item::weapon::Weapon {
  3265. weapon: item::weapon::WeaponType::Handgun,
  3266. grind: 0,
  3267. special: None,
  3268. attrs: [None, None, None],
  3269. tekked: true,
  3270. kills: None,
  3271. }
  3272. ),
  3273. }).await.unwrap());
  3274. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3275. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3276. let mut ship = Box::new(ShipServerState::builder()
  3277. .gateway(entity_gateway.clone())
  3278. .build());
  3279. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3280. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3281. join_lobby(&mut ship, ClientId(1)).await;
  3282. join_lobby(&mut ship, ClientId(2)).await;
  3283. create_room(&mut ship, ClientId(1), "room", "").await;
  3284. join_room(&mut ship, ClientId(2), 0).await;
  3285. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3286. assert_eq!(p1_items.items.len(), 1);
  3287. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3288. assert_eq!(p2_items.items.len(), 0);
  3289. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3290. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3291. client: 1,
  3292. target: 0,
  3293. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3294. })))).await.unwrap().for_each(drop);
  3295. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3296. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3297. let titems = TradeItemBuilder::default()
  3298. .individual(&p1_items.items[0], 0x10001)
  3299. .build();
  3300. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3301. trade_target: 1,
  3302. unknown2: 0,
  3303. count: 1,
  3304. items: titems,
  3305. })).await.unwrap().collect::<Vec<_>>();
  3306. assert_eq!(ack.len(), 2);
  3307. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3308. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3309. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3310. assert_eq!(p1_items.items.len(), 1);
  3311. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3312. assert_eq!(p2_items.items.len(), 0);
  3313. }
  3314. #[async_std::test]
  3315. async fn test_stack_is_same_amount_in_request_and_items_to_trade() {
  3316. let mut entity_gateway = InMemoryGateway::default();
  3317. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3318. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3319. let p1_stack = futures::future::join_all((0..2).map(|_| {
  3320. let mut entity_gateway = entity_gateway.clone();
  3321. async move {
  3322. entity_gateway.create_item(
  3323. item::NewItemEntity {
  3324. item: item::ItemDetail::Tool(
  3325. item::tool::Tool {
  3326. tool: item::tool::ToolType::Monomate,
  3327. }
  3328. )
  3329. }).await
  3330. }}))
  3331. .await
  3332. .into_iter()
  3333. .collect::<Result<Vec<ItemEntity>,_>>()
  3334. .unwrap();
  3335. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  3336. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3337. let mut ship = Box::new(ShipServerState::builder()
  3338. .gateway(entity_gateway.clone())
  3339. .build());
  3340. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3341. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3342. join_lobby(&mut ship, ClientId(1)).await;
  3343. join_lobby(&mut ship, ClientId(2)).await;
  3344. create_room(&mut ship, ClientId(1), "room", "").await;
  3345. join_room(&mut ship, ClientId(2), 0).await;
  3346. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3347. assert_eq!(p1_items.items.len(), 1);
  3348. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3349. assert_eq!(p2_items.items.len(), 0);
  3350. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3351. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3352. client: 1,
  3353. target: 0,
  3354. trade: TradeRequestCommand::AddItem(0x10000, 2)
  3355. })))).await.unwrap().for_each(drop);
  3356. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3357. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3358. let titems = TradeItemBuilder::default()
  3359. .stacked(&p1_items.items[0], 0x10000, 1)
  3360. .build();
  3361. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3362. trade_target: 1,
  3363. unknown2: 0,
  3364. count: 1,
  3365. items: titems,
  3366. })).await.unwrap().collect::<Vec<_>>();
  3367. assert_eq!(ack.len(), 2);
  3368. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3369. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3370. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3371. assert_eq!(p1_items.items.len(), 1);
  3372. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3373. assert_eq!(p2_items.items.len(), 0);
  3374. }
  3375. #[async_std::test]
  3376. async fn test_stack_is_same_amount_in_request_and_items_to_trade2() {
  3377. let mut entity_gateway = InMemoryGateway::default();
  3378. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3379. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3380. let p1_stack = futures::future::join_all((0..2).map(|_| {
  3381. let mut entity_gateway = entity_gateway.clone();
  3382. async move {
  3383. entity_gateway.create_item(
  3384. item::NewItemEntity {
  3385. item: item::ItemDetail::Tool(
  3386. item::tool::Tool {
  3387. tool: item::tool::ToolType::Monomate,
  3388. }
  3389. )
  3390. }).await
  3391. }}))
  3392. .await
  3393. .into_iter()
  3394. .collect::<Result<Vec<ItemEntity>,_>>()
  3395. .unwrap();
  3396. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
  3397. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3398. let mut ship = Box::new(ShipServerState::builder()
  3399. .gateway(entity_gateway.clone())
  3400. .build());
  3401. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3402. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3403. join_lobby(&mut ship, ClientId(1)).await;
  3404. join_lobby(&mut ship, ClientId(2)).await;
  3405. create_room(&mut ship, ClientId(1), "room", "").await;
  3406. join_room(&mut ship, ClientId(2), 0).await;
  3407. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3408. assert_eq!(p1_items.items.len(), 1);
  3409. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3410. assert_eq!(p2_items.items.len(), 0);
  3411. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3412. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3413. client: 1,
  3414. target: 0,
  3415. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3416. })))).await.unwrap().for_each(drop);
  3417. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3418. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3419. let titems = TradeItemBuilder::default()
  3420. .stacked(&p1_items.items[0], 0x10000, 2)
  3421. .build();
  3422. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3423. trade_target: 1,
  3424. unknown2: 0,
  3425. count: 1,
  3426. items: titems,
  3427. })).await.unwrap().collect::<Vec<_>>();
  3428. assert_eq!(ack.len(), 2);
  3429. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3430. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3431. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3432. assert_eq!(p1_items.items.len(), 1);
  3433. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3434. assert_eq!(p2_items.items.len(), 0);
  3435. }
  3436. #[async_std::test]
  3437. async fn test_items_to_trade_count_less_than() {
  3438. let mut entity_gateway = InMemoryGateway::default();
  3439. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3440. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3441. let p1_inv = vec![
  3442. entity_gateway.create_item(
  3443. item::NewItemEntity {
  3444. item: item::ItemDetail::Weapon(
  3445. item::weapon::Weapon {
  3446. weapon: item::weapon::WeaponType::Saber,
  3447. grind: 0,
  3448. special: None,
  3449. attrs: [None, None, None],
  3450. tekked: true,
  3451. kills: None,
  3452. }
  3453. ),
  3454. }).await.unwrap(),
  3455. entity_gateway.create_item(
  3456. item::NewItemEntity {
  3457. item: item::ItemDetail::Weapon(
  3458. item::weapon::Weapon {
  3459. weapon: item::weapon::WeaponType::Brand,
  3460. grind: 0,
  3461. special: None,
  3462. attrs: [None, None, None],
  3463. tekked: true,
  3464. kills: None,
  3465. }
  3466. ),
  3467. }).await.unwrap(),
  3468. entity_gateway.create_item(
  3469. item::NewItemEntity {
  3470. item: item::ItemDetail::Weapon(
  3471. item::weapon::Weapon {
  3472. weapon: item::weapon::WeaponType::Buster,
  3473. grind: 0,
  3474. special: None,
  3475. attrs: [None, None, None],
  3476. tekked: true,
  3477. kills: None,
  3478. }
  3479. ),
  3480. }).await.unwrap(),
  3481. ];
  3482. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3483. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3484. let mut ship = Box::new(ShipServerState::builder()
  3485. .gateway(entity_gateway.clone())
  3486. .build());
  3487. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3488. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3489. join_lobby(&mut ship, ClientId(1)).await;
  3490. join_lobby(&mut ship, ClientId(2)).await;
  3491. create_room(&mut ship, ClientId(1), "room", "").await;
  3492. join_room(&mut ship, ClientId(2), 0).await;
  3493. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3494. assert_eq!(p1_items.items.len(), 3);
  3495. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3496. assert_eq!(p2_items.items.len(), 0);
  3497. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3498. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3499. client: 1,
  3500. target: 0,
  3501. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3502. })))).await.unwrap().for_each(drop);
  3503. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3504. client: 1,
  3505. target: 0,
  3506. trade: TradeRequestCommand::AddItem(0x10001, 1)
  3507. })))).await.unwrap().for_each(drop);
  3508. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3509. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3510. let titems = TradeItemBuilder::default()
  3511. .individual(&p1_items.items[0], 0x10000)
  3512. .individual(&p1_items.items[1], 0x10001)
  3513. .build();
  3514. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3515. trade_target: 1,
  3516. unknown2: 0,
  3517. count: 1,
  3518. items: titems,
  3519. })).await.unwrap().collect::<Vec<_>>();
  3520. assert_eq!(ack.len(), 2);
  3521. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3522. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3523. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3524. assert_eq!(p1_items.items.len(), 3);
  3525. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3526. assert_eq!(p2_items.items.len(), 0);
  3527. }
  3528. #[async_std::test]
  3529. async fn test_items_to_trade_count_greater_than() {
  3530. let mut entity_gateway = InMemoryGateway::default();
  3531. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3532. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3533. entity_gateway.set_character_meseta(&char1.id, Meseta(23)).await.unwrap();
  3534. let p1_inv = vec![
  3535. entity_gateway.create_item(
  3536. item::NewItemEntity {
  3537. item: item::ItemDetail::Weapon(
  3538. item::weapon::Weapon {
  3539. weapon: item::weapon::WeaponType::Saber,
  3540. grind: 0,
  3541. special: None,
  3542. attrs: [None, None, None],
  3543. tekked: true,
  3544. kills: None,
  3545. }
  3546. ),
  3547. }).await.unwrap(),
  3548. entity_gateway.create_item(
  3549. item::NewItemEntity {
  3550. item: item::ItemDetail::Weapon(
  3551. item::weapon::Weapon {
  3552. weapon: item::weapon::WeaponType::Brand,
  3553. grind: 0,
  3554. special: None,
  3555. attrs: [None, None, None],
  3556. tekked: true,
  3557. kills: None,
  3558. }
  3559. ),
  3560. }).await.unwrap(),
  3561. entity_gateway.create_item(
  3562. item::NewItemEntity {
  3563. item: item::ItemDetail::Weapon(
  3564. item::weapon::Weapon {
  3565. weapon: item::weapon::WeaponType::Buster,
  3566. grind: 0,
  3567. special: None,
  3568. attrs: [None, None, None],
  3569. tekked: true,
  3570. kills: None,
  3571. }
  3572. ),
  3573. }).await.unwrap(),
  3574. ];
  3575. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3576. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3577. let mut ship = Box::new(ShipServerState::builder()
  3578. .gateway(entity_gateway.clone())
  3579. .build());
  3580. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3581. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3582. join_lobby(&mut ship, ClientId(1)).await;
  3583. join_lobby(&mut ship, ClientId(2)).await;
  3584. create_room(&mut ship, ClientId(1), "room", "").await;
  3585. join_room(&mut ship, ClientId(2), 0).await;
  3586. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3587. assert_eq!(p1_items.items.len(), 3);
  3588. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3589. assert_eq!(p2_items.items.len(), 0);
  3590. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3591. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3592. client: 1,
  3593. target: 0,
  3594. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3595. })))).await.unwrap().for_each(drop);
  3596. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3597. client: 1,
  3598. target: 0,
  3599. trade: TradeRequestCommand::AddItem(0x10001, 1)
  3600. })))).await.unwrap().for_each(drop);
  3601. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3602. client: 1,
  3603. target: 0,
  3604. trade: TradeRequestCommand::AddItem(0xFFFFFF01, 5)
  3605. })))).await.unwrap().for_each(drop);
  3606. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3607. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3608. let titems = TradeItemBuilder::default()
  3609. .individual(&p1_items.items[0], 0x10000)
  3610. .individual(&p1_items.items[1], 0x10001)
  3611. .meseta(5)
  3612. .build();
  3613. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3614. trade_target: 1,
  3615. unknown2: 0,
  3616. count: 4,
  3617. items: titems,
  3618. })).await.unwrap().collect::<Vec<_>>();
  3619. assert_eq!(ack.len(), 2);
  3620. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3621. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3622. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3623. assert_eq!(p1_items.items.len(), 3);
  3624. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3625. assert_eq!(p2_items.items.len(), 0);
  3626. }
  3627. #[async_std::test]
  3628. async fn test_items_to_trade_count_mismatch_with_meseta() {
  3629. let mut entity_gateway = InMemoryGateway::default();
  3630. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3631. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3632. let p1_inv = vec![
  3633. entity_gateway.create_item(
  3634. item::NewItemEntity {
  3635. item: item::ItemDetail::Weapon(
  3636. item::weapon::Weapon {
  3637. weapon: item::weapon::WeaponType::Saber,
  3638. grind: 0,
  3639. special: None,
  3640. attrs: [None, None, None],
  3641. tekked: true,
  3642. kills: None,
  3643. }
  3644. ),
  3645. }).await.unwrap(),
  3646. entity_gateway.create_item(
  3647. item::NewItemEntity {
  3648. item: item::ItemDetail::Weapon(
  3649. item::weapon::Weapon {
  3650. weapon: item::weapon::WeaponType::Brand,
  3651. grind: 0,
  3652. special: None,
  3653. attrs: [None, None, None],
  3654. tekked: true,
  3655. kills: None,
  3656. }
  3657. ),
  3658. }).await.unwrap(),
  3659. entity_gateway.create_item(
  3660. item::NewItemEntity {
  3661. item: item::ItemDetail::Weapon(
  3662. item::weapon::Weapon {
  3663. weapon: item::weapon::WeaponType::Buster,
  3664. grind: 0,
  3665. special: None,
  3666. attrs: [None, None, None],
  3667. tekked: true,
  3668. kills: None,
  3669. }
  3670. ),
  3671. }).await.unwrap(),
  3672. ];
  3673. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3674. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3675. let mut ship = Box::new(ShipServerState::builder()
  3676. .gateway(entity_gateway.clone())
  3677. .build());
  3678. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3679. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3680. join_lobby(&mut ship, ClientId(1)).await;
  3681. join_lobby(&mut ship, ClientId(2)).await;
  3682. create_room(&mut ship, ClientId(1), "room", "").await;
  3683. join_room(&mut ship, ClientId(2), 0).await;
  3684. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3685. assert_eq!(p1_items.items.len(), 3);
  3686. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3687. assert_eq!(p2_items.items.len(), 0);
  3688. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3689. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3690. client: 1,
  3691. target: 0,
  3692. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3693. })))).await.unwrap().for_each(drop);
  3694. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3695. client: 1,
  3696. target: 0,
  3697. trade: TradeRequestCommand::AddItem(0x10001, 1)
  3698. })))).await.unwrap().for_each(drop);
  3699. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3700. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3701. let titems = TradeItemBuilder::default()
  3702. .individual(&p1_items.items[0], 0x10000)
  3703. .individual(&p1_items.items[1], 0x10001)
  3704. .build();
  3705. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3706. trade_target: 1,
  3707. unknown2: 0,
  3708. count: 3,
  3709. items: titems,
  3710. })).await.unwrap().collect::<Vec<_>>();
  3711. assert_eq!(ack.len(), 2);
  3712. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
  3713. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
  3714. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3715. assert_eq!(p1_items.items.len(), 3);
  3716. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3717. assert_eq!(p2_items.items.len(), 0);
  3718. }
  3719. #[async_std::test]
  3720. async fn test_dropping_item_after_trade() {
  3721. let mut entity_gateway = InMemoryGateway::default();
  3722. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  3723. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  3724. let mut p1_inv = Vec::new();
  3725. p1_inv.push(entity_gateway.create_item(
  3726. item::NewItemEntity {
  3727. item: item::ItemDetail::Weapon(
  3728. item::weapon::Weapon {
  3729. weapon: item::weapon::WeaponType::Handgun,
  3730. grind: 0,
  3731. special: None,
  3732. attrs: [None, None, None],
  3733. tekked: true,
  3734. kills: None,
  3735. }
  3736. ),
  3737. }).await.unwrap());
  3738. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  3739. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
  3740. let mut ship = Box::new(ShipServerState::builder()
  3741. .gateway(entity_gateway.clone())
  3742. .build());
  3743. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  3744. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  3745. join_lobby(&mut ship, ClientId(1)).await;
  3746. join_lobby(&mut ship, ClientId(2)).await;
  3747. create_room(&mut ship, ClientId(1), "room", "").await;
  3748. join_room(&mut ship, ClientId(2), 0).await;
  3749. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3750. assert_eq!(p1_items.items.len(), 1);
  3751. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3752. assert_eq!(p2_items.items.len(), 0);
  3753. initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3754. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
  3755. client: 1,
  3756. target: 0,
  3757. trade: TradeRequestCommand::AddItem(0x10000, 1)
  3758. })))).await.unwrap().for_each(drop);
  3759. confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3760. finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
  3761. let titems = TradeItemBuilder::default()
  3762. .individual(&p1_items.items[0], 0x10000)
  3763. .build();
  3764. let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3765. trade_target: 1,
  3766. unknown2: 0,
  3767. count: 1,
  3768. items: titems,
  3769. })).await.unwrap().collect::<Vec<_>>();
  3770. assert_eq!(ack.len(), 0);
  3771. let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
  3772. trade_target: 0,
  3773. unknown2: 0,
  3774. count: 0,
  3775. items: Default::default(),
  3776. })).await.unwrap().collect::<Vec<_>>();
  3777. assert_eq!(ack.len(), 2);
  3778. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3779. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
  3780. let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3781. })).await.unwrap().collect::<Vec<_>>();
  3782. assert_eq!(ack.len(), 0);
  3783. let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
  3784. })).await.unwrap().collect::<Vec<_>>();
  3785. assert_eq!(ack.len(), 5);
  3786. assert!(matches!(ack[0], (ClientId(2), SendShipPacket::Message(Message {
  3787. msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
  3788. ..
  3789. }))));
  3790. assert!(matches!(ack[1], (ClientId(1), SendShipPacket::Message(Message {
  3791. msg: GameMessage::CreateItem(CreateItem {..}),
  3792. ..
  3793. }))));
  3794. assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
  3795. msg: GameMessage::CreateItem(CreateItem {..}),
  3796. ..
  3797. }))));
  3798. assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
  3799. assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
  3800. let _ack = ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  3801. client: 0,
  3802. target: 0,
  3803. unknown1: 0,
  3804. map_area: 0,
  3805. item_id: 0x810001,
  3806. x: 0.0,
  3807. y: 0.0,
  3808. z: 0.0,
  3809. })))).await.unwrap().for_each(drop);
  3810. let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  3811. assert_eq!(p1_items.items.len(), 0);
  3812. let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
  3813. assert_eq!(p2_items.items.len(), 0);
  3814. }