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.

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