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.

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