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.

4364 lines
176 KiB

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