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.

1699 lines
64 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. use std::collections::BTreeSet;
  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};
  6. use libpso::packet::ship::*;
  7. use libpso::packet::messages::*;
  8. #[path = "common.rs"]
  9. mod common;
  10. use common::*;
  11. #[async_std::test]
  12. async fn test_bank_items_sent_in_character_login() {
  13. let mut entity_gateway = InMemoryGateway::default();
  14. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  15. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  16. let item = entity_gateway.create_item(
  17. item::NewItemEntity {
  18. item: item::ItemDetail::Weapon(
  19. item::weapon::Weapon {
  20. weapon: item::weapon::WeaponType::Vulcan,
  21. grind: 0,
  22. special: None,
  23. attrs: [None, None, None],
  24. tekked: true,
  25. }
  26. ),
  27. location: item::ItemLocation::Bank {
  28. character_id: char1.id,
  29. name: item::BankName("".to_string())
  30. }
  31. }).await.unwrap();
  32. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![item]), item::BankName("".into())).await.unwrap();
  33. let mut ship = Box::new(ShipServerState::builder()
  34. .gateway(entity_gateway.clone())
  35. .build());
  36. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  37. let packets = ship.handle(ClientId(1), &RecvShipPacket::MenuSelect(MenuSelect {
  38. menu: BLOCK_MENU_ID,
  39. item: 1,
  40. })).await.unwrap().collect::<Vec<_>>();
  41. assert!(matches!(&packets[0], (_, SendShipPacket::FullCharacter(fc)) if fc.character.bank.items[0].data1[0..3] == [0x00, 0x08, 0x04] ));
  42. }
  43. #[async_std::test]
  44. async fn test_request_bank_items() {
  45. let mut entity_gateway = InMemoryGateway::default();
  46. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  47. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  48. let mut bank = Vec::new();
  49. for _ in 0..3 {
  50. bank.push(entity_gateway.create_item(
  51. item::NewItemEntity {
  52. item: item::ItemDetail::Weapon(
  53. item::weapon::Weapon {
  54. weapon: item::weapon::WeaponType::Vulcan,
  55. grind: 0,
  56. special: None,
  57. attrs: [None, None, None],
  58. tekked: true,
  59. }
  60. ),
  61. location: item::ItemLocation::Bank {
  62. character_id: char1.id,
  63. name: item::BankName("".to_string())
  64. }
  65. }).await.unwrap());
  66. }
  67. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(bank), item::BankName("".into())).await.unwrap();
  68. let mut ship = Box::new(ShipServerState::builder()
  69. .gateway(entity_gateway.clone())
  70. .build());
  71. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  72. join_lobby(&mut ship, ClientId(1)).await;
  73. create_room(&mut ship, ClientId(1), "room", "").await;
  74. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  75. client: 0,
  76. target: 0,
  77. unknown: 0,
  78. })))).await.unwrap().collect::<Vec<_>>();
  79. assert!(matches!(&packets[0], (_, SendShipPacket::BankItemList (bank_item_list))
  80. if bank_item_list.item_count == 3
  81. && bank_item_list.size == 0x18 * 3 + 0x14
  82. && bank_item_list.items[0].data1[0..3] == [0x00, 0x08, 0x04]
  83. && bank_item_list.items[1].data1[0..3] == [0x00, 0x08, 0x04]
  84. && bank_item_list.items[2].data1[0..3] == [0x00, 0x08, 0x04]
  85. ));
  86. }
  87. #[async_std::test]
  88. async fn test_request_stacked_bank_items() {
  89. let mut entity_gateway = InMemoryGateway::default();
  90. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  91. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  92. let mut monomates = Vec::new();
  93. for _ in 0..3usize {
  94. monomates.push(entity_gateway.create_item(
  95. item::NewItemEntity {
  96. item: item::ItemDetail::Tool (
  97. item::tool::Tool {
  98. tool: item::tool::ToolType::Monomate,
  99. }
  100. ),
  101. location: item::ItemLocation::Bank {
  102. character_id: char1.id,
  103. name: item::BankName("".to_string())
  104. }
  105. }).await.unwrap());
  106. }
  107. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![monomates]), item::BankName("".into())).await.unwrap();
  108. let mut ship = Box::new(ShipServerState::builder()
  109. .gateway(entity_gateway.clone())
  110. .build());
  111. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  112. join_lobby(&mut ship, ClientId(1)).await;
  113. create_room(&mut ship, ClientId(1), "room", "").await;
  114. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  115. client: 0,
  116. target: 0,
  117. unknown: 0,
  118. })))).await.unwrap().collect::<Vec<_>>();
  119. assert!(matches!(&packets[0], (_, SendShipPacket::BankItemList (bank_item_list))
  120. if bank_item_list.item_count == 1
  121. && bank_item_list.size == 0x18 + 0x14
  122. && bank_item_list.items[0].data1[0..3] == [0x03, 0x00, 0x00]
  123. && bank_item_list.items[0].amount == 3
  124. ));
  125. }
  126. #[async_std::test]
  127. async fn test_request_bank_items_sorted() {
  128. let mut entity_gateway = InMemoryGateway::default();
  129. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  130. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  131. let item1 = entity_gateway.create_item(
  132. item::NewItemEntity {
  133. item: item::ItemDetail::Weapon(
  134. item::weapon::Weapon {
  135. weapon: item::weapon::WeaponType::Vulcan,
  136. grind: 0,
  137. special: None,
  138. attrs: [None, None, None],
  139. tekked: true,
  140. }
  141. ),
  142. location: item::ItemLocation::Bank {
  143. character_id: char1.id,
  144. name: item::BankName("".to_string())
  145. }
  146. }).await.unwrap();
  147. let monomate = entity_gateway.create_item(
  148. item::NewItemEntity {
  149. item: item::ItemDetail::Tool (
  150. item::tool::Tool {
  151. tool: item::tool::ToolType::Monomate,
  152. }
  153. ),
  154. location: item::ItemLocation::Bank {
  155. character_id: char1.id,
  156. name: item::BankName("".to_string())
  157. }
  158. }).await.unwrap();
  159. let item2 = entity_gateway.create_item(
  160. item::NewItemEntity {
  161. item: item::ItemDetail::Weapon(
  162. item::weapon::Weapon {
  163. weapon: item::weapon::WeaponType::Calibur,
  164. grind: 0,
  165. special: None,
  166. attrs: [None, None, None],
  167. tekked: true,
  168. }
  169. ),
  170. location: item::ItemLocation::Bank {
  171. character_id: char1.id,
  172. name: item::BankName("".to_string())
  173. }
  174. }).await.unwrap();
  175. let bank = vec![item::BankItemEntity::Individual(item1), vec![monomate].into(), item2.into()];
  176. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(bank), item::BankName("".into())).await.unwrap();
  177. let mut ship = Box::new(ShipServerState::builder()
  178. .gateway(entity_gateway.clone())
  179. .build());
  180. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  181. join_lobby(&mut ship, ClientId(1)).await;
  182. create_room(&mut ship, ClientId(1), "room", "").await;
  183. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  184. client: 0,
  185. target: 0,
  186. unknown: 0,
  187. })))).await.unwrap().collect::<Vec<_>>();
  188. assert!(matches!(&packets[0], (_, SendShipPacket::BankItemList (bank_item_list))
  189. if bank_item_list.item_count == 3
  190. && bank_item_list.size == 0x18 * 3 + 0x14
  191. && bank_item_list.items[0].data1[0..3] == [0x00, 0x02, 0x04]
  192. && bank_item_list.items[1].data1[0..3] == [0x00, 0x08, 0x04]
  193. && bank_item_list.items[2].data1[0..3] == [0x03, 0x00, 0x00]
  194. ));
  195. }
  196. #[async_std::test]
  197. async fn test_deposit_individual_item() {
  198. let mut entity_gateway = InMemoryGateway::default();
  199. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  200. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  201. let item0 = entity_gateway.create_item(
  202. item::NewItemEntity {
  203. item: item::ItemDetail::Weapon(
  204. item::weapon::Weapon {
  205. weapon: item::weapon::WeaponType::Saber,
  206. grind: 0,
  207. special: None,
  208. attrs: [None, None, None],
  209. tekked: true,
  210. }
  211. ),
  212. location: item::ItemLocation::Inventory {
  213. character_id: char1.id,
  214. }
  215. }).await.unwrap();
  216. let item1 = entity_gateway.create_item(
  217. item::NewItemEntity {
  218. item: item::ItemDetail::Weapon(
  219. item::weapon::Weapon {
  220. weapon: item::weapon::WeaponType::Handgun,
  221. grind: 0,
  222. special: None,
  223. attrs: [None, None, None],
  224. tekked: true,
  225. }
  226. ),
  227. location: item::ItemLocation::Inventory {
  228. character_id: char1.id,
  229. }
  230. }).await.unwrap();
  231. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![item0, item1])).await.unwrap();
  232. let mut ship = Box::new(ShipServerState::builder()
  233. .gateway(entity_gateway.clone())
  234. .build());
  235. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  236. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  237. join_lobby(&mut ship, ClientId(1)).await;
  238. join_lobby(&mut ship, ClientId(2)).await;
  239. create_room(&mut ship, ClientId(1), "room", "").await;
  240. join_room(&mut ship, ClientId(2), 0).await;
  241. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  242. client: 0,
  243. target: 0,
  244. unknown: 0,
  245. })))).await.unwrap().for_each(drop);
  246. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  247. client: 0,
  248. target: 0,
  249. item_id: 0x10001,
  250. action: 0,
  251. item_amount: 0,
  252. meseta_amount: 0,
  253. unknown: 0,
  254. })))).await.unwrap().collect::<Vec<_>>();
  255. assert!(packets.len() == 2);
  256. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
  257. if player_no_longer_has_item.item_id == 0x10001
  258. && player_no_longer_has_item.amount == 0
  259. ));
  260. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  261. assert_eq!(bank_items.items.len(), 1);
  262. bank_items.items[0].with_individual(|item| {
  263. assert_eq!(item.id, item::ItemEntityId(2));
  264. }).unwrap();
  265. }
  266. #[async_std::test]
  267. async fn test_deposit_stacked_item() {
  268. let mut entity_gateway = InMemoryGateway::default();
  269. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  270. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  271. let mut monomates = Vec::new();
  272. for _ in 0..3usize {
  273. monomates.push(entity_gateway.create_item(
  274. item::NewItemEntity {
  275. item: item::ItemDetail::Tool(
  276. item::tool::Tool {
  277. tool: item::tool::ToolType::Monomate,
  278. }
  279. ),
  280. location: item::ItemLocation::Inventory {
  281. character_id: char1.id,
  282. }
  283. }).await.unwrap());
  284. }
  285. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![monomates])).await.unwrap();
  286. let mut ship = Box::new(ShipServerState::builder()
  287. .gateway(entity_gateway.clone())
  288. .build());
  289. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  290. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  291. join_lobby(&mut ship, ClientId(1)).await;
  292. join_lobby(&mut ship, ClientId(2)).await;
  293. create_room(&mut ship, ClientId(1), "room", "").await;
  294. join_room(&mut ship, ClientId(2), 0).await;
  295. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  296. client: 0,
  297. target: 0,
  298. unknown: 0,
  299. })))).await.unwrap().for_each(drop);
  300. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  301. client: 0,
  302. target: 0,
  303. item_id: 0x10000,
  304. action: 0,
  305. item_amount: 3,
  306. meseta_amount: 0,
  307. unknown: 0,
  308. })))).await.unwrap().collect::<Vec<_>>();
  309. assert!(packets.len() == 2);
  310. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
  311. if player_no_longer_has_item.item_id == 0x10000
  312. && player_no_longer_has_item.amount == 3
  313. ));
  314. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  315. assert_eq!(bank_items.items.len(), 1);
  316. bank_items.items[0].with_stacked(|items| {
  317. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  318. vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3)]);
  319. }).unwrap();
  320. }
  321. #[async_std::test]
  322. async fn test_deposit_partial_stacked_item() {
  323. let mut entity_gateway = InMemoryGateway::default();
  324. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  325. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  326. let mut monomates = Vec::new();
  327. for _ in 0..3usize {
  328. monomates.push(entity_gateway.create_item(
  329. item::NewItemEntity {
  330. item: item::ItemDetail::Tool(
  331. item::tool::Tool {
  332. tool: item::tool::ToolType::Monomate,
  333. }
  334. ),
  335. location: item::ItemLocation::Inventory {
  336. character_id: char1.id,
  337. }
  338. }).await.unwrap());
  339. }
  340. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![monomates])).await.unwrap();
  341. let mut ship = Box::new(ShipServerState::builder()
  342. .gateway(entity_gateway.clone())
  343. .build());
  344. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  345. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  346. join_lobby(&mut ship, ClientId(1)).await;
  347. join_lobby(&mut ship, ClientId(2)).await;
  348. create_room(&mut ship, ClientId(1), "room", "").await;
  349. join_room(&mut ship, ClientId(2), 0).await;
  350. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  351. client: 0,
  352. target: 0,
  353. unknown: 0,
  354. })))).await.unwrap().for_each(drop);
  355. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  356. client: 0,
  357. target: 0,
  358. item_id: 0x10000,
  359. action: 0,
  360. item_amount: 2,
  361. meseta_amount: 0,
  362. unknown: 0,
  363. })))).await.unwrap().collect::<Vec<_>>();
  364. assert!(packets.len() == 2);
  365. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
  366. if player_no_longer_has_item.item_id == 0x10000
  367. && player_no_longer_has_item.amount == 2
  368. ));
  369. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  370. assert_eq!(bank_items.items.len(), 1);
  371. bank_items.items[0].with_stacked(|items| {
  372. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  373. vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
  374. }).unwrap();
  375. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  376. assert_eq!(inventory_items.items.len(), 1);
  377. inventory_items.items[0].with_stacked(|items| {
  378. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  379. vec![item::ItemEntityId(3)]);
  380. }).unwrap();
  381. }
  382. #[async_std::test]
  383. async fn test_deposit_stacked_item_with_stack_already_in_bank() {
  384. let mut entity_gateway = InMemoryGateway::default();
  385. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  386. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  387. let mut bank_monomates = Vec::new();
  388. let mut inventory_monomates = Vec::new();
  389. for _ in 0..2usize {
  390. inventory_monomates.push(entity_gateway.create_item(
  391. item::NewItemEntity {
  392. item: item::ItemDetail::Tool(
  393. item::tool::Tool {
  394. tool: item::tool::ToolType::Monomate,
  395. }
  396. ),
  397. location: item::ItemLocation::Inventory {
  398. character_id: char1.id,
  399. }
  400. }).await.unwrap());
  401. bank_monomates.push(entity_gateway.create_item(
  402. item::NewItemEntity {
  403. item: item::ItemDetail::Tool(
  404. item::tool::Tool {
  405. tool: item::tool::ToolType::Monomate,
  406. }
  407. ),
  408. location: item::ItemLocation::Bank {
  409. character_id: char1.id,
  410. name: item::BankName("".into()),
  411. }
  412. }).await.unwrap());
  413. }
  414. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![inventory_monomates])).await.unwrap();
  415. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![bank_monomates]), item::BankName("".into())).await.unwrap();
  416. let mut ship = Box::new(ShipServerState::builder()
  417. .gateway(entity_gateway.clone())
  418. .build());
  419. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  420. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  421. join_lobby(&mut ship, ClientId(1)).await;
  422. join_lobby(&mut ship, ClientId(2)).await;
  423. create_room(&mut ship, ClientId(1), "room", "").await;
  424. join_room(&mut ship, ClientId(2), 0).await;
  425. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  426. client: 0,
  427. target: 0,
  428. unknown: 0,
  429. })))).await.unwrap().for_each(drop);
  430. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  431. client: 0,
  432. target: 0,
  433. item_id: 0x10000,
  434. action: 0,
  435. item_amount: 2,
  436. meseta_amount: 0,
  437. unknown: 0,
  438. })))).await.unwrap().collect::<Vec<_>>();
  439. assert!(packets.len() == 2);
  440. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
  441. if player_no_longer_has_item.item_id == 0x10000
  442. && player_no_longer_has_item.amount == 2
  443. ));
  444. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  445. assert_eq!(bank_items.items.len(), 1);
  446. bank_items.items[0].with_stacked(|items| {
  447. assert_eq!(items.iter().map(|i| i.id).collect::<BTreeSet<_>>(),
  448. vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3), item::ItemEntityId(4)].into_iter().collect::<BTreeSet<_>>() );
  449. }).unwrap();
  450. }
  451. #[async_std::test]
  452. async fn test_deposit_stacked_item_with_full_stack_in_bank() {
  453. let mut entity_gateway = InMemoryGateway::default();
  454. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  455. let mut inventory_monomates = Vec::new();
  456. for _ in 0..2usize {
  457. inventory_monomates.push(entity_gateway.create_item(
  458. item::NewItemEntity {
  459. item: item::ItemDetail::Tool(
  460. item::tool::Tool {
  461. tool: item::tool::ToolType::Monomate,
  462. }
  463. ),
  464. location: item::ItemLocation::Inventory {
  465. character_id: char1.id,
  466. }
  467. }).await.unwrap());
  468. }
  469. let mut bank_monomates = Vec::new();
  470. for _ in 0..10 {
  471. bank_monomates.push(entity_gateway.create_item(
  472. item::NewItemEntity {
  473. item: item::ItemDetail::Tool(
  474. item::tool::Tool {
  475. tool: item::tool::ToolType::Monomate,
  476. }
  477. ),
  478. location: item::ItemLocation::Bank {
  479. character_id: char1.id,
  480. name: item::BankName("".into()),
  481. }
  482. }).await.unwrap());
  483. }
  484. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![inventory_monomates])).await.unwrap();
  485. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![bank_monomates]), item::BankName("".into())).await.unwrap();
  486. let mut ship = Box::new(ShipServerState::builder()
  487. .gateway(entity_gateway.clone())
  488. .build());
  489. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  490. join_lobby(&mut ship, ClientId(1)).await;
  491. create_room(&mut ship, ClientId(1), "room", "").await;
  492. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  493. client: 0,
  494. target: 0,
  495. unknown: 0,
  496. })))).await.unwrap().for_each(drop);
  497. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  498. client: 0,
  499. target: 0,
  500. item_id: 0x10000,
  501. action: 0,
  502. item_amount: 2,
  503. meseta_amount: 0,
  504. unknown: 0,
  505. })))).await;
  506. assert!(packets.is_err());
  507. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  508. assert_eq!(bank_items.items.len(), 1);
  509. bank_items.items[0].with_stacked(|items| {
  510. assert_eq!(items.len(), 10);
  511. }).unwrap();
  512. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  513. assert_eq!(inventory_items.items.len(), 1);
  514. inventory_items.items[0].with_stacked(|items| {
  515. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  516. vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
  517. }).unwrap();
  518. }
  519. #[async_std::test]
  520. async fn test_deposit_individual_item_in_full_bank() {
  521. let mut entity_gateway = InMemoryGateway::default();
  522. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  523. let mut inventory = Vec::new();
  524. inventory.push(entity_gateway.create_item(
  525. item::NewItemEntity {
  526. item: item::ItemDetail::Weapon(
  527. item::weapon::Weapon {
  528. weapon: item::weapon::WeaponType::Vulcan,
  529. grind: 0,
  530. special: None,
  531. attrs: [None, None, None],
  532. tekked: true,
  533. }
  534. ),
  535. location: item::ItemLocation::Inventory {
  536. character_id: char1.id,
  537. }
  538. }).await.unwrap());
  539. let mut bank = Vec::new();
  540. for _ in 0..200usize {
  541. bank.push(entity_gateway.create_item(
  542. item::NewItemEntity {
  543. item: item::ItemDetail::Weapon(
  544. item::weapon::Weapon {
  545. weapon: item::weapon::WeaponType::Vulcan,
  546. grind: 0,
  547. special: None,
  548. attrs: [None, None, None],
  549. tekked: true,
  550. }
  551. ),
  552. location: item::ItemLocation::Bank {
  553. character_id: char1.id,
  554. name: item::BankName("".to_string())
  555. }
  556. }).await.unwrap());
  557. }
  558. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(inventory)).await.unwrap();
  559. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(bank), item::BankName("".into())).await.unwrap();
  560. let mut ship = Box::new(ShipServerState::builder()
  561. .gateway(entity_gateway.clone())
  562. .build());
  563. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  564. join_lobby(&mut ship, ClientId(1)).await;
  565. create_room(&mut ship, ClientId(1), "room", "").await;
  566. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  567. client: 0,
  568. target: 0,
  569. unknown: 0,
  570. })))).await.unwrap().for_each(drop);
  571. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  572. client: 0,
  573. target: 0,
  574. item_id: 0x10000,
  575. action: 0,
  576. item_amount: 0,
  577. meseta_amount: 0,
  578. unknown: 0,
  579. })))).await;
  580. assert!(packets.is_err());
  581. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  582. assert_eq!(bank_items.items.len(), 200);
  583. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  584. assert_eq!(inventory_items.items.len(), 1);
  585. inventory_items.items[0].with_individual(|item| {
  586. assert_eq!(item.id, item::ItemEntityId(1));
  587. }).unwrap();
  588. }
  589. #[async_std::test]
  590. async fn test_deposit_stacked_item_in_full_bank() {
  591. let mut entity_gateway = InMemoryGateway::default();
  592. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  593. let mut monomates = Vec::new();
  594. for _ in 0..2usize {
  595. monomates.push(entity_gateway.create_item(
  596. item::NewItemEntity {
  597. item: item::ItemDetail::Tool(
  598. item::tool::Tool {
  599. tool: item::tool::ToolType::Monomate,
  600. }
  601. ),
  602. location: item::ItemLocation::Inventory {
  603. character_id: char1.id,
  604. }
  605. }).await.unwrap());
  606. }
  607. let mut full_bank = Vec::new();
  608. for _ in 0..200usize {
  609. full_bank.push(entity_gateway.create_item(
  610. item::NewItemEntity {
  611. item: item::ItemDetail::Weapon(
  612. item::weapon::Weapon {
  613. weapon: item::weapon::WeaponType::Vulcan,
  614. grind: 0,
  615. special: None,
  616. attrs: [None, None, None],
  617. tekked: true,
  618. }
  619. ),
  620. location: item::ItemLocation::Bank {
  621. character_id: char1.id,
  622. name: item::BankName("".to_string())
  623. }
  624. }).await.unwrap());
  625. }
  626. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![monomates])).await.unwrap();
  627. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(full_bank), item::BankName("".into())).await.unwrap();
  628. let mut ship = Box::new(ShipServerState::builder()
  629. .gateway(entity_gateway.clone())
  630. .build());
  631. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  632. join_lobby(&mut ship, ClientId(1)).await;
  633. create_room(&mut ship, ClientId(1), "room", "").await;
  634. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  635. client: 0,
  636. target: 0,
  637. unknown: 0,
  638. })))).await.unwrap().for_each(drop);
  639. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  640. client: 0,
  641. target: 0,
  642. item_id: 0x10000,
  643. action: 0,
  644. item_amount: 2,
  645. meseta_amount: 0,
  646. unknown: 0,
  647. })))).await;
  648. assert!(packets.is_err());
  649. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  650. assert_eq!(bank_items.items.len(), 200);
  651. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  652. assert_eq!(inventory_items.items.len(), 1);
  653. inventory_items.items[0].with_stacked(|items| {
  654. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  655. vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
  656. }).unwrap();
  657. }
  658. #[async_std::test]
  659. async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
  660. let mut entity_gateway = InMemoryGateway::default();
  661. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  662. let mut monomates = Vec::new();
  663. for _ in 0..2usize {
  664. monomates.push(entity_gateway.create_item(
  665. item::NewItemEntity {
  666. item: item::ItemDetail::Tool(
  667. item::tool::Tool {
  668. tool: item::tool::ToolType::Monomate,
  669. }
  670. ),
  671. location: item::ItemLocation::Inventory {
  672. character_id: char1.id,
  673. }
  674. }).await.unwrap());
  675. }
  676. let mut bank_monomates = Vec::new();
  677. for _ in 0..2usize {
  678. bank_monomates.push(entity_gateway.create_item(
  679. item::NewItemEntity {
  680. item: item::ItemDetail::Tool(
  681. item::tool::Tool {
  682. tool: item::tool::ToolType::Monomate,
  683. }
  684. ),
  685. location: item::ItemLocation::Bank {
  686. character_id: char1.id,
  687. name: item::BankName("".to_string())
  688. }
  689. }).await.unwrap());
  690. }
  691. let mut almost_full_bank: Vec<item::BankItemEntity> = Vec::new();
  692. for _ in 0..199usize {
  693. almost_full_bank.push(entity_gateway.create_item(
  694. item::NewItemEntity {
  695. item: item::ItemDetail::Weapon(
  696. item::weapon::Weapon {
  697. weapon: item::weapon::WeaponType::Vulcan,
  698. grind: 0,
  699. special: None,
  700. attrs: [None, None, None],
  701. tekked: true,
  702. }
  703. ),
  704. location: item::ItemLocation::Bank {
  705. character_id: char1.id,
  706. name: item::BankName("".to_string())
  707. }
  708. }).await.unwrap().into());
  709. }
  710. almost_full_bank.push(bank_monomates.into());
  711. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![monomates])).await.unwrap();
  712. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(almost_full_bank), item::BankName("".into())).await.unwrap();
  713. let mut ship = Box::new(ShipServerState::builder()
  714. .gateway(entity_gateway.clone())
  715. .build());
  716. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  717. join_lobby(&mut ship, ClientId(1)).await;
  718. create_room(&mut ship, ClientId(1), "room", "").await;
  719. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  720. client: 0,
  721. target: 0,
  722. unknown: 0,
  723. })))).await.unwrap().for_each(drop);
  724. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  725. client: 0,
  726. target: 0,
  727. item_id: 0x10000,
  728. action: 0,
  729. item_amount: 2,
  730. meseta_amount: 0,
  731. unknown: 0,
  732. })))).await.unwrap().for_each(drop);
  733. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  734. assert_eq!(bank_items.items.len(), 200);
  735. bank_items.items[199].with_stacked(|items| {
  736. assert_eq!(items.len(), 4);
  737. }).unwrap();
  738. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  739. assert_eq!(inventory_items.items.len(), 0);
  740. }
  741. #[async_std::test]
  742. async fn test_deposit_meseta() {
  743. let mut entity_gateway = InMemoryGateway::default();
  744. let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  745. char1.meseta = 300;
  746. entity_gateway.save_character(&char1).await.unwrap();
  747. let mut ship = Box::new(ShipServerState::builder()
  748. .gateway(entity_gateway.clone())
  749. .build());
  750. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  751. join_lobby(&mut ship, ClientId(1)).await;
  752. create_room(&mut ship, ClientId(1), "room", "").await;
  753. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  754. client: 0,
  755. target: 0,
  756. unknown: 0,
  757. })))).await.unwrap().for_each(drop);
  758. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  759. client: 0,
  760. target: 0,
  761. item_id: 0xFFFFFFFF,
  762. action: 0,
  763. item_amount: 0,
  764. meseta_amount: 23,
  765. unknown: 0,
  766. })))).await.unwrap().for_each(drop);
  767. let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
  768. let char = characters[0].as_ref().unwrap();
  769. assert!(char.meseta == 277);
  770. assert!(char.bank_meseta == 23);
  771. }
  772. #[async_std::test]
  773. async fn test_deposit_too_much_meseta() {
  774. let mut entity_gateway = InMemoryGateway::default();
  775. let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  776. char1.meseta = 300;
  777. char1.bank_meseta = 999980;
  778. entity_gateway.save_character(&char1).await.unwrap();
  779. let mut ship = Box::new(ShipServerState::builder()
  780. .gateway(entity_gateway.clone())
  781. .build());
  782. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  783. join_lobby(&mut ship, ClientId(1)).await;
  784. create_room(&mut ship, ClientId(1), "room", "").await;
  785. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  786. client: 0,
  787. target: 0,
  788. unknown: 0,
  789. })))).await.unwrap().for_each(drop);
  790. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  791. client: 0,
  792. target: 0,
  793. item_id: 0xFFFFFFFF,
  794. action: 0,
  795. item_amount: 0,
  796. meseta_amount: 23,
  797. unknown: 0,
  798. })))).await.unwrap().for_each(drop);
  799. let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
  800. let char = characters[0].as_ref().unwrap();
  801. assert!(char.meseta == 300);
  802. assert!(char.bank_meseta == 999980);
  803. }
  804. #[async_std::test]
  805. async fn test_deposit_meseta_when_bank_is_maxed() {
  806. let mut entity_gateway = InMemoryGateway::default();
  807. let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  808. char1.meseta = 300;
  809. char1.bank_meseta = 999999;
  810. entity_gateway.save_character(&char1).await.unwrap();
  811. let mut ship = Box::new(ShipServerState::builder()
  812. .gateway(entity_gateway.clone())
  813. .build());
  814. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  815. join_lobby(&mut ship, ClientId(1)).await;
  816. create_room(&mut ship, ClientId(1), "room", "").await;
  817. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  818. client: 0,
  819. target: 0,
  820. unknown: 0,
  821. })))).await.unwrap().for_each(drop);
  822. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  823. client: 0,
  824. target: 0,
  825. item_id: 0xFFFFFFFF,
  826. action: 0,
  827. item_amount: 0,
  828. meseta_amount: 23,
  829. unknown: 0,
  830. })))).await.unwrap().for_each(drop);
  831. let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
  832. let char = characters[0].as_ref().unwrap();
  833. assert!(char.meseta == 300);
  834. assert!(char.bank_meseta == 999999);
  835. }
  836. #[async_std::test]
  837. async fn test_withdraw_individual_item() {
  838. let mut entity_gateway = InMemoryGateway::default();
  839. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  840. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  841. let mut bank = Vec::new();
  842. bank.push(entity_gateway.create_item(
  843. item::NewItemEntity {
  844. item: item::ItemDetail::Weapon(
  845. item::weapon::Weapon {
  846. weapon: item::weapon::WeaponType::Saber,
  847. grind: 0,
  848. special: None,
  849. attrs: [None, None, None],
  850. tekked: true,
  851. }
  852. ),
  853. location: item::ItemLocation::Bank {
  854. character_id: char1.id,
  855. name: item::BankName("".to_string())
  856. }
  857. }).await.unwrap());
  858. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(bank), item::BankName("".into())).await.unwrap();
  859. let mut ship = Box::new(ShipServerState::builder()
  860. .gateway(entity_gateway.clone())
  861. .build());
  862. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  863. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  864. join_lobby(&mut ship, ClientId(1)).await;
  865. join_lobby(&mut ship, ClientId(2)).await;
  866. create_room(&mut ship, ClientId(1), "room", "").await;
  867. join_room(&mut ship, ClientId(2), 0).await;
  868. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  869. client: 0,
  870. target: 0,
  871. unknown: 0,
  872. })))).await.unwrap().for_each(drop);
  873. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  874. client: 0,
  875. target: 0,
  876. item_id: 0x20000,
  877. action: 1,
  878. item_amount: 0,
  879. meseta_amount: 0,
  880. unknown: 0,
  881. })))).await.unwrap().collect::<Vec<_>>();
  882. assert!(packets.len() == 2);
  883. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::CreateItem(create_item)}))
  884. if create_item.item_id == 0x20000
  885. ));
  886. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  887. assert_eq!(inventory_items.items.len(), 1);
  888. inventory_items.items[0].with_individual(|item| {
  889. assert_eq!(item.id, item::ItemEntityId(1));
  890. }).unwrap();
  891. }
  892. #[async_std::test]
  893. async fn test_withdraw_stacked_item() {
  894. let mut entity_gateway = InMemoryGateway::default();
  895. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  896. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  897. let mut monomates = Vec::new();
  898. for _ in 0..3usize {
  899. monomates.push(entity_gateway.create_item(
  900. item::NewItemEntity {
  901. item: item::ItemDetail::Tool(
  902. item::tool::Tool {
  903. tool: item::tool::ToolType::Monomate,
  904. }
  905. ),
  906. location: item::ItemLocation::Bank {
  907. character_id: char1.id,
  908. name: item::BankName("".to_string())
  909. }
  910. }).await.unwrap());
  911. }
  912. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![monomates]), item::BankName("".into())).await.unwrap();
  913. let mut ship = Box::new(ShipServerState::builder()
  914. .gateway(entity_gateway.clone())
  915. .build());
  916. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  917. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  918. join_lobby(&mut ship, ClientId(1)).await;
  919. join_lobby(&mut ship, ClientId(2)).await;
  920. create_room(&mut ship, ClientId(1), "room", "").await;
  921. join_room(&mut ship, ClientId(2), 0).await;
  922. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  923. client: 0,
  924. target: 0,
  925. unknown: 0,
  926. })))).await.unwrap().for_each(drop);
  927. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  928. client: 0,
  929. target: 0,
  930. item_id: 0x20000,
  931. action: 1,
  932. item_amount: 3,
  933. meseta_amount: 0,
  934. unknown: 0,
  935. })))).await.unwrap().collect::<Vec<_>>();
  936. assert!(packets.len() == 2);
  937. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::CreateItem(create_item)}))
  938. if create_item.item_id == 0x10002
  939. ));
  940. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  941. assert_eq!(inventory_items.items.len(), 1);
  942. inventory_items.items[0].with_stacked(|items| {
  943. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  944. vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3)]);
  945. }).unwrap();
  946. }
  947. #[async_std::test]
  948. async fn test_withdraw_partial_stacked_item() {
  949. let mut entity_gateway = InMemoryGateway::default();
  950. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  951. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  952. let mut monomates = Vec::new();
  953. for _ in 0..3usize {
  954. monomates.push(entity_gateway.create_item(
  955. item::NewItemEntity {
  956. item: item::ItemDetail::Tool(
  957. item::tool::Tool {
  958. tool: item::tool::ToolType::Monomate,
  959. }
  960. ),
  961. location: item::ItemLocation::Bank {
  962. character_id: char1.id,
  963. name: item::BankName("".into())
  964. }
  965. }).await.unwrap());
  966. }
  967. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![monomates]), item::BankName("".into())).await.unwrap();
  968. let mut ship = Box::new(ShipServerState::builder()
  969. .gateway(entity_gateway.clone())
  970. .build());
  971. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  972. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  973. join_lobby(&mut ship, ClientId(1)).await;
  974. join_lobby(&mut ship, ClientId(2)).await;
  975. create_room(&mut ship, ClientId(1), "room", "").await;
  976. join_room(&mut ship, ClientId(2), 0).await;
  977. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  978. client: 0,
  979. target: 0,
  980. unknown: 0,
  981. })))).await.unwrap().for_each(drop);
  982. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  983. client: 0,
  984. target: 0,
  985. item_id: 0x20000,
  986. action: 1,
  987. item_amount: 2,
  988. meseta_amount: 0,
  989. unknown: 0,
  990. })))).await.unwrap().collect::<Vec<_>>();
  991. assert!(packets.len() == 2);
  992. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::CreateItem(create_item)}))
  993. if create_item.item_id == 0x10002
  994. ));
  995. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  996. assert_eq!(bank_items.items.len(), 1);
  997. bank_items.items[0].with_stacked(|items| {
  998. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  999. vec![item::ItemEntityId(3)]);
  1000. }).unwrap();
  1001. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1002. assert_eq!(inventory_items.items.len(), 1);
  1003. inventory_items.items[0].with_stacked(|items| {
  1004. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  1005. vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
  1006. }).unwrap();
  1007. }
  1008. #[async_std::test]
  1009. async fn test_withdraw_stacked_item_with_stack_already_in_inventory() {
  1010. let mut entity_gateway = InMemoryGateway::default();
  1011. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1012. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  1013. let mut inventory_monomates = Vec::new();
  1014. let mut bank_monomates = Vec::new();
  1015. for _ in 0..2usize {
  1016. inventory_monomates.push(entity_gateway.create_item(
  1017. item::NewItemEntity {
  1018. item: item::ItemDetail::Tool(
  1019. item::tool::Tool {
  1020. tool: item::tool::ToolType::Monomate,
  1021. }
  1022. ),
  1023. location: item::ItemLocation::Inventory {
  1024. character_id: char1.id,
  1025. }
  1026. }).await.unwrap());
  1027. bank_monomates.push(entity_gateway.create_item(
  1028. item::NewItemEntity {
  1029. item: item::ItemDetail::Tool(
  1030. item::tool::Tool {
  1031. tool: item::tool::ToolType::Monomate,
  1032. }
  1033. ),
  1034. location: item::ItemLocation::Bank {
  1035. character_id: char1.id,
  1036. name: item::BankName("".into()),
  1037. }
  1038. }).await.unwrap());
  1039. }
  1040. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![inventory_monomates])).await.unwrap();
  1041. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![bank_monomates]), item::BankName("".into())).await.unwrap();
  1042. let mut ship = Box::new(ShipServerState::builder()
  1043. .gateway(entity_gateway.clone())
  1044. .build());
  1045. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1046. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  1047. join_lobby(&mut ship, ClientId(1)).await;
  1048. join_lobby(&mut ship, ClientId(2)).await;
  1049. create_room(&mut ship, ClientId(1), "room", "").await;
  1050. join_room(&mut ship, ClientId(2), 0).await;
  1051. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1052. client: 0,
  1053. target: 0,
  1054. unknown: 0,
  1055. })))).await.unwrap().for_each(drop);
  1056. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1057. client: 0,
  1058. target: 0,
  1059. item_id: 0x20000,
  1060. action: 1,
  1061. item_amount: 2,
  1062. meseta_amount: 0,
  1063. unknown: 0,
  1064. })))).await.unwrap().collect::<Vec<_>>();
  1065. assert!(packets.len() == 2);
  1066. assert!(matches!(&packets[1], (ClientId(2), SendShipPacket::Message(Message {msg: GameMessage::CreateItem(create_item)}))
  1067. if create_item.item_id == 0x10000
  1068. ));
  1069. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  1070. assert_eq!(bank_items.items.len(), 0);
  1071. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1072. assert_eq!(inventory_items.items.len(), 1);
  1073. inventory_items.items[0].with_stacked(|items| {
  1074. assert_eq!(items.iter().map(|i| i.id).collect::<BTreeSet<_>>(),
  1075. vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3), item::ItemEntityId(4)].into_iter().collect::<BTreeSet<_>>());
  1076. }).unwrap();
  1077. }
  1078. #[async_std::test]
  1079. async fn test_withdraw_stacked_item_with_full_stack_in_inventory() {
  1080. let mut entity_gateway = InMemoryGateway::default();
  1081. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1082. let mut bank_monomates = Vec::new();
  1083. for _ in 0..2usize {
  1084. bank_monomates.push(entity_gateway.create_item(
  1085. item::NewItemEntity {
  1086. item: item::ItemDetail::Tool(
  1087. item::tool::Tool {
  1088. tool: item::tool::ToolType::Monomate,
  1089. }
  1090. ),
  1091. location: item::ItemLocation::Bank {
  1092. character_id: char1.id,
  1093. name: item::BankName("".into()),
  1094. }
  1095. }).await.unwrap());
  1096. }
  1097. let mut inventory_monomates = Vec::new();
  1098. for _ in 0..10usize {
  1099. inventory_monomates.push(entity_gateway.create_item(
  1100. item::NewItemEntity {
  1101. item: item::ItemDetail::Tool(
  1102. item::tool::Tool {
  1103. tool: item::tool::ToolType::Monomate,
  1104. }
  1105. ),
  1106. location: item::ItemLocation::Inventory {
  1107. character_id: char1.id,
  1108. }
  1109. }).await.unwrap());
  1110. }
  1111. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![inventory_monomates])).await.unwrap();
  1112. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![bank_monomates]), item::BankName("".into())).await.unwrap();
  1113. let mut ship = Box::new(ShipServerState::builder()
  1114. .gateway(entity_gateway.clone())
  1115. .build());
  1116. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1117. join_lobby(&mut ship, ClientId(1)).await;
  1118. create_room(&mut ship, ClientId(1), "room", "").await;
  1119. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1120. client: 0,
  1121. target: 0,
  1122. unknown: 0,
  1123. })))).await.unwrap().for_each(drop);
  1124. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1125. client: 0,
  1126. target: 0,
  1127. item_id: 0x20000,
  1128. action: 1,
  1129. item_amount: 2,
  1130. meseta_amount: 0,
  1131. unknown: 0,
  1132. })))).await;
  1133. assert!(packets.is_err());
  1134. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  1135. assert_eq!(bank_items.items.len(), 1);
  1136. bank_items.items[0].with_stacked(|items| {
  1137. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  1138. vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
  1139. }).unwrap();
  1140. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1141. assert_eq!(inventory_items.items.len(), 1);
  1142. inventory_items.items[0].with_stacked(|items| {
  1143. assert_eq!(items.len(), 10);
  1144. }).unwrap();
  1145. }
  1146. #[async_std::test]
  1147. async fn test_withdraw_individual_item_in_full_inventory() {
  1148. let mut entity_gateway = InMemoryGateway::default();
  1149. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1150. let mut bank = Vec::new();
  1151. bank.push(entity_gateway.create_item(
  1152. item::NewItemEntity {
  1153. item: item::ItemDetail::Weapon(
  1154. item::weapon::Weapon {
  1155. weapon: item::weapon::WeaponType::Vulcan,
  1156. grind: 0,
  1157. special: None,
  1158. attrs: [None, None, None],
  1159. tekked: true,
  1160. }
  1161. ),
  1162. location: item::ItemLocation::Bank {
  1163. character_id: char1.id,
  1164. name: item::BankName("".to_string())
  1165. }
  1166. }).await.unwrap());
  1167. let mut inventory = Vec::new();
  1168. for _ in 0..30usize {
  1169. inventory.push(entity_gateway.create_item(
  1170. item::NewItemEntity {
  1171. item: item::ItemDetail::Weapon(
  1172. item::weapon::Weapon {
  1173. weapon: item::weapon::WeaponType::Vulcan,
  1174. grind: 0,
  1175. special: None,
  1176. attrs: [None, None, None],
  1177. tekked: true,
  1178. }
  1179. ),
  1180. location: item::ItemLocation::Inventory {
  1181. character_id: char1.id,
  1182. }
  1183. }).await.unwrap());
  1184. }
  1185. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(inventory)).await.unwrap();
  1186. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(bank), item::BankName("".into())).await.unwrap();
  1187. let mut ship = Box::new(ShipServerState::builder()
  1188. .gateway(entity_gateway.clone())
  1189. .build());
  1190. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1191. join_lobby(&mut ship, ClientId(1)).await;
  1192. create_room(&mut ship, ClientId(1), "room", "").await;
  1193. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1194. client: 0,
  1195. target: 0,
  1196. unknown: 0,
  1197. })))).await.unwrap().for_each(drop);
  1198. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1199. client: 0,
  1200. target: 0,
  1201. item_id: 0x20000,
  1202. action: 1,
  1203. item_amount: 0,
  1204. meseta_amount: 0,
  1205. unknown: 0,
  1206. })))).await;
  1207. assert!(packets.is_err());
  1208. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  1209. assert_eq!(bank_items.items.len(), 1);
  1210. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1211. assert_eq!(inventory_items.items.len(), 30);
  1212. }
  1213. #[async_std::test]
  1214. async fn test_withdraw_stacked_item_in_full_inventory() {
  1215. let mut entity_gateway = InMemoryGateway::default();
  1216. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1217. let mut monomates = Vec::new();
  1218. for _ in 0..2usize {
  1219. monomates.push(entity_gateway.create_item(
  1220. item::NewItemEntity {
  1221. item: item::ItemDetail::Tool(
  1222. item::tool::Tool {
  1223. tool: item::tool::ToolType::Monomate,
  1224. }
  1225. ),
  1226. location: item::ItemLocation::Bank {
  1227. character_id: char1.id,
  1228. name: item::BankName("".to_string())
  1229. }
  1230. }).await.unwrap());
  1231. }
  1232. let mut inventory = Vec::new();
  1233. for _ in 0..30usize {
  1234. inventory.push(entity_gateway.create_item(
  1235. item::NewItemEntity {
  1236. item: item::ItemDetail::Weapon(
  1237. item::weapon::Weapon {
  1238. weapon: item::weapon::WeaponType::Vulcan,
  1239. grind: 0,
  1240. special: None,
  1241. attrs: [None, None, None],
  1242. tekked: true,
  1243. }
  1244. ),
  1245. location: item::ItemLocation::Inventory {
  1246. character_id: char1.id,
  1247. }
  1248. }).await.unwrap());
  1249. }
  1250. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(inventory)).await.unwrap();
  1251. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![monomates]), item::BankName("".into())).await.unwrap();
  1252. let mut ship = Box::new(ShipServerState::builder()
  1253. .gateway(entity_gateway.clone())
  1254. .build());
  1255. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1256. join_lobby(&mut ship, ClientId(1)).await;
  1257. create_room(&mut ship, ClientId(1), "room", "").await;
  1258. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1259. client: 0,
  1260. target: 0,
  1261. unknown: 0,
  1262. })))).await.unwrap().for_each(drop);
  1263. let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1264. client: 0,
  1265. target: 0,
  1266. item_id: 0x20000,
  1267. action: 1,
  1268. item_amount: 2,
  1269. meseta_amount: 0,
  1270. unknown: 0,
  1271. })))).await;
  1272. assert!(packets.is_err());
  1273. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  1274. assert_eq!(bank_items.items.len(), 1);
  1275. bank_items.items[0].with_stacked(|items| {
  1276. assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
  1277. vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
  1278. }).unwrap();
  1279. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1280. assert_eq!(inventory_items.items.len(), 30);
  1281. }
  1282. #[async_std::test]
  1283. async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() {
  1284. let mut entity_gateway = InMemoryGateway::default();
  1285. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1286. let mut bank_item = Vec::new();
  1287. for _ in 0..2usize {
  1288. bank_item.push(entity_gateway.create_item(
  1289. item::NewItemEntity {
  1290. item: item::ItemDetail::Tool(
  1291. item::tool::Tool {
  1292. tool: item::tool::ToolType::Monomate,
  1293. }
  1294. ),
  1295. location: item::ItemLocation::Bank {
  1296. character_id: char1.id,
  1297. name: item::BankName("".to_string())
  1298. }
  1299. }).await.unwrap());
  1300. }
  1301. entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![bank_item]), item::BankName("".into())).await.unwrap();
  1302. let mut items = Vec::new();
  1303. for i in 0..29usize {
  1304. items.push(entity_gateway.create_item(
  1305. item::NewItemEntity {
  1306. item: item::ItemDetail::Weapon(
  1307. item::weapon::Weapon {
  1308. weapon: item::weapon::WeaponType::Vulcan,
  1309. grind: 0,
  1310. special: None,
  1311. attrs: [None, None, None],
  1312. tekked: true,
  1313. }
  1314. ),
  1315. location: item::ItemLocation::Inventory {
  1316. character_id: char1.id,
  1317. }
  1318. }).await.unwrap().into());
  1319. }
  1320. let mut item29 = Vec::new();
  1321. for _ in 0..2usize {
  1322. item29.push(entity_gateway.create_item(
  1323. item::NewItemEntity {
  1324. item: item::ItemDetail::Tool(
  1325. item::tool::Tool {
  1326. tool: item::tool::ToolType::Monomate,
  1327. }
  1328. ),
  1329. location: item::ItemLocation::Inventory {
  1330. character_id: char1.id,
  1331. }
  1332. }).await.unwrap());
  1333. }
  1334. items.push(item::InventoryItemEntity::Stacked(item29));
  1335. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(items)).await.unwrap();
  1336. let mut ship = Box::new(ShipServerState::builder()
  1337. .gateway(entity_gateway.clone())
  1338. .build());
  1339. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1340. join_lobby(&mut ship, ClientId(1)).await;
  1341. create_room(&mut ship, ClientId(1), "room", "").await;
  1342. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1343. client: 0,
  1344. target: 0,
  1345. unknown: 0,
  1346. })))).await.unwrap().for_each(drop);
  1347. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1348. client: 0,
  1349. target: 0,
  1350. item_id: 0x20000,
  1351. action: 1,
  1352. item_amount: 2,
  1353. meseta_amount: 0,
  1354. unknown: 0,
  1355. })))).await.unwrap().for_each(drop);
  1356. let bank_items = entity_gateway.get_character_bank(&char1.id, item::BankName("".into())).await.unwrap();
  1357. assert!(bank_items.items.len() == 0);
  1358. let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
  1359. assert!(inventory_items.items.len() == 30);
  1360. match &inventory_items.items[29] {
  1361. item::InventoryItemEntity::Stacked(items) => {
  1362. assert_eq!(items.len(), 4);
  1363. },
  1364. _ => panic!(),
  1365. }
  1366. }
  1367. #[async_std::test]
  1368. async fn test_withdraw_meseta() {
  1369. let mut entity_gateway = InMemoryGateway::default();
  1370. let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1371. char1.bank_meseta = 300;
  1372. entity_gateway.save_character(&char1).await.unwrap();
  1373. let mut ship = Box::new(ShipServerState::builder()
  1374. .gateway(entity_gateway.clone())
  1375. .build());
  1376. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1377. join_lobby(&mut ship, ClientId(1)).await;
  1378. create_room(&mut ship, ClientId(1), "room", "").await;
  1379. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1380. client: 0,
  1381. target: 0,
  1382. unknown: 0,
  1383. })))).await.unwrap().for_each(drop);
  1384. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1385. client: 0,
  1386. target: 0,
  1387. item_id: 0xFFFFFFFF,
  1388. action: 1,
  1389. item_amount: 0,
  1390. meseta_amount: 23,
  1391. unknown: 0,
  1392. })))).await.unwrap().for_each(drop);
  1393. let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
  1394. let char = characters[0].as_ref().unwrap();
  1395. assert!(char.meseta == 23);
  1396. assert!(char.bank_meseta == 277);
  1397. }
  1398. #[async_std::test]
  1399. async fn test_withdraw_too_much_meseta() {
  1400. let mut entity_gateway = InMemoryGateway::default();
  1401. let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1402. char1.meseta = 999980;
  1403. char1.bank_meseta = 300;
  1404. entity_gateway.save_character(&char1).await.unwrap();
  1405. let mut ship = Box::new(ShipServerState::builder()
  1406. .gateway(entity_gateway.clone())
  1407. .build());
  1408. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1409. join_lobby(&mut ship, ClientId(1)).await;
  1410. create_room(&mut ship, ClientId(1), "room", "").await;
  1411. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1412. client: 0,
  1413. target: 0,
  1414. unknown: 0,
  1415. })))).await.unwrap().for_each(drop);
  1416. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1417. client: 0,
  1418. target: 0,
  1419. item_id: 0xFFFFFFFF,
  1420. action: 1,
  1421. item_amount: 0,
  1422. meseta_amount: 23,
  1423. unknown: 0,
  1424. })))).await.unwrap().for_each(drop);
  1425. let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
  1426. let char = characters[0].as_ref().unwrap();
  1427. assert!(char.meseta == 999980);
  1428. assert!(char.bank_meseta == 300);
  1429. }
  1430. #[async_std::test]
  1431. async fn test_withdraw_meseta_inventory_is_maxed() {
  1432. let mut entity_gateway = InMemoryGateway::default();
  1433. let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  1434. char1.meseta = 999999;
  1435. char1.bank_meseta = 300;
  1436. entity_gateway.save_character(&char1).await.unwrap();
  1437. let mut ship = Box::new(ShipServerState::builder()
  1438. .gateway(entity_gateway.clone())
  1439. .build());
  1440. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  1441. join_lobby(&mut ship, ClientId(1)).await;
  1442. create_room(&mut ship, ClientId(1), "room", "").await;
  1443. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
  1444. client: 0,
  1445. target: 0,
  1446. unknown: 0,
  1447. })))).await.unwrap().for_each(drop);
  1448. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
  1449. client: 0,
  1450. target: 0,
  1451. item_id: 0xFFFFFFFF,
  1452. action: 1,
  1453. item_amount: 0,
  1454. meseta_amount: 23,
  1455. unknown: 0,
  1456. })))).await.unwrap().for_each(drop);
  1457. let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
  1458. let char = characters[0].as_ref().unwrap();
  1459. assert!(char.meseta == 999999);
  1460. assert!(char.bank_meseta == 300);
  1461. }