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.

4365 lines
176 KiB

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