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.

1768 lines
60 KiB

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