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.

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