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.

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