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.

749 lines
27 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. use std::time::SystemTime;
  2. use elseware::common::serverstate::{ClientId, ServerState};
  3. use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
  4. use elseware::entity::account::{UserAccountEntity, NewUserAccountEntity, NewUserSettingsEntity};
  5. use elseware::entity::character::{CharacterEntity, NewCharacterEntity};
  6. //use elseware::entity::item::{NewItemEntity, ItemDetail, ItemLocation};
  7. use elseware::entity::item;
  8. use elseware::ship::ship::{ShipServerState, RecvShipPacket};
  9. use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType};
  10. use libpso::packet::ship::*;
  11. use libpso::packet::messages::*;
  12. use libpso::packet::login::{Login, Session};
  13. use libpso::{utf8_to_array, utf8_to_utf16_array};
  14. pub async fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, username: &str, password: &str) -> (UserAccountEntity, CharacterEntity) {
  15. let new_user = NewUserAccountEntity {
  16. username: username.into(),
  17. password: bcrypt::hash(password, 5).unwrap(),
  18. guildcard: 1,
  19. team_id: None,
  20. banned: false,
  21. muted_until: SystemTime::now(),
  22. created_at: SystemTime::now(),
  23. flags: 0,
  24. };
  25. let user = entity_gateway.create_user(new_user).await.unwrap();
  26. let new_settings = NewUserSettingsEntity::new(user.id);
  27. let _settings = entity_gateway.create_user_settings(new_settings).await.unwrap();
  28. let new_character = NewCharacterEntity::new(user.id);
  29. let character = entity_gateway.create_character(new_character).await.unwrap();
  30. (user, character)
  31. }
  32. pub async fn log_in_char<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, username: &str, password: &str) {
  33. let username = username.to_string();
  34. let password = password.to_string();
  35. ship.handle(id, &RecvShipPacket::Login(Login {
  36. tag: 0,
  37. guildcard: 0,
  38. version: 0,
  39. unknown1: [0; 6],
  40. team: 0,
  41. username: utf8_to_array!(username, 16),
  42. unknown2: [0; 32],
  43. password: utf8_to_array!(password, 16),
  44. unknown3: [0; 40],
  45. hwinfo: [0; 8],
  46. session: Session::new(),
  47. })).await.unwrap().for_each(drop);
  48. }
  49. pub async fn join_lobby<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId) {
  50. ship.handle(id, &RecvShipPacket::CharData(CharData {
  51. _unknown: [0; 0x828]
  52. })).await.unwrap().for_each(drop);
  53. }
  54. pub async fn create_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str) {
  55. ship.handle(id, &RecvShipPacket::CreateRoom(CreateRoom {
  56. unknown: [0; 2],
  57. name: utf8_to_utf16_array!(name, 16),
  58. password: utf8_to_utf16_array!(password, 16),
  59. difficulty: 0,
  60. battle: 0,
  61. challenge: 0,
  62. episode: 1,
  63. single_player: 0,
  64. padding: [0; 3],
  65. })).await.unwrap().for_each(drop);
  66. ship.handle(id, &RecvShipPacket::DoneBursting(DoneBursting {})).await.unwrap().for_each(drop);
  67. }
  68. pub async fn join_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, room_id: u32) {
  69. ship.handle(id, &RecvShipPacket::MenuSelect(MenuSelect {
  70. menu: ROOM_MENU_ID,
  71. item: room_id,
  72. })).await.unwrap().for_each(drop);
  73. }
  74. #[async_std::test]
  75. async fn test_pick_up_item_stack_of_items_already_in_inventory() {
  76. let mut entity_gateway = InMemoryGateway::new();
  77. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  78. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  79. entity_gateway.create_item(
  80. item::NewItemEntity {
  81. item: item::ItemDetail::Tool(
  82. item::tool::Tool {
  83. tool: item::tool::ToolType::Monomate
  84. }
  85. ),
  86. location: item::ItemLocation::Inventory {
  87. character_id: char1.id,
  88. slot: 0,
  89. equipped: false,
  90. }
  91. }).await;
  92. for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
  93. for _ in 0..5 {
  94. entity_gateway.create_item(
  95. item::NewItemEntity {
  96. item: item::ItemDetail::Tool(
  97. item::tool::Tool {
  98. tool: tool
  99. }
  100. ),
  101. location: item::ItemLocation::Inventory {
  102. character_id: char2.id,
  103. slot: slot,
  104. equipped: false,
  105. }
  106. }).await;
  107. }
  108. }
  109. let mut ship = ShipServerState::new(entity_gateway.clone());
  110. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  111. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  112. join_lobby(&mut ship, ClientId(1)).await;
  113. join_lobby(&mut ship, ClientId(2)).await;
  114. create_room(&mut ship, ClientId(1), "room", "").await;
  115. join_room(&mut ship, ClientId(2), 0).await;
  116. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  117. client: 0,
  118. target: 0,
  119. unknown1: 0,
  120. area: 0,
  121. item_id: 0x210000,
  122. x: 0.0,
  123. y: 0.0,
  124. z: 0.0,
  125. })))).await.unwrap().for_each(drop);
  126. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  127. client: 0,
  128. target: 0,
  129. item_id: 0x210000,
  130. area: 0,
  131. unknown: [0; 3]
  132. })))).await.unwrap().for_each(drop);
  133. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  134. assert!(p1_inventory.count() == 1);
  135. let inventory_item = p1_inventory.slot(0).unwrap();
  136. assert!(inventory_item.entity_id == ActiveItemEntityId::Stacked(vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3), item::ItemEntityId(4), item::ItemEntityId(5), item::ItemEntityId(6)]));
  137. assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
  138. }
  139. #[async_std::test]
  140. async fn test_pick_up_item_stack_of_items_not_already_held() {
  141. let mut entity_gateway = InMemoryGateway::new();
  142. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  143. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").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::Inventory {
  152. character_id: char2.id,
  153. slot: 0,
  154. equipped: false,
  155. }
  156. }).await;
  157. let mut ship = ShipServerState::new(entity_gateway.clone());
  158. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  159. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  160. join_lobby(&mut ship, ClientId(1)).await;
  161. join_lobby(&mut ship, ClientId(2)).await;
  162. create_room(&mut ship, ClientId(1), "room", "").await;
  163. join_room(&mut ship, ClientId(2), 0).await;
  164. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  165. client: 0,
  166. target: 0,
  167. unknown1: 0,
  168. area: 0,
  169. item_id: 0x210000,
  170. x: 0.0,
  171. y: 0.0,
  172. z: 0.0,
  173. })))).await.unwrap().for_each(drop);
  174. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  175. client: 0,
  176. target: 0,
  177. item_id: 0x210000,
  178. area: 0,
  179. unknown: [0; 3]
  180. })))).await.unwrap().for_each(drop);
  181. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  182. assert!(p1_inventory.count() == 1);
  183. let inventory_item = p1_inventory.slot(0).unwrap();
  184. assert!(inventory_item.entity_id == ActiveItemEntityId::Stacked(vec![item::ItemEntityId(1)]));
  185. assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 1));
  186. }
  187. #[async_std::test]
  188. async fn test_pick_up_meseta_when_inventory_full() {
  189. let mut entity_gateway = InMemoryGateway::new();
  190. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  191. let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  192. for slot in 0..30 {
  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: slot,
  207. equipped: false,
  208. }
  209. }).await;
  210. }
  211. char2.meseta = 300;
  212. entity_gateway.save_character(&char2).await;
  213. let mut ship = ShipServerState::new(entity_gateway.clone());
  214. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  215. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  216. join_lobby(&mut ship, ClientId(1)).await;
  217. join_lobby(&mut ship, ClientId(2)).await;
  218. create_room(&mut ship, ClientId(1), "room", "").await;
  219. join_room(&mut ship, ClientId(2), 0).await;
  220. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
  221. client: 0,
  222. target: 0,
  223. item_id: 0xFFFFFFFF,
  224. map_area: 0,
  225. x: 0.0,
  226. z: 0.0,
  227. })))).await.unwrap().for_each(drop);
  228. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
  229. client: 0,
  230. target: 0,
  231. item_id: 0xFFFFFFFF,
  232. amount: 23,
  233. })))).await.unwrap().for_each(drop);
  234. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  235. client: 0,
  236. target: 0,
  237. item_id: 0xF0000001,
  238. area: 0,
  239. unknown: [0; 3]
  240. })))).await.unwrap().for_each(drop);
  241. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  242. assert!(p1_inventory.count() == 30);
  243. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  244. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  245. assert!(c1.character.meseta == 23);
  246. assert!(c2.character.meseta == 277);
  247. }
  248. #[async_std::test]
  249. async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
  250. let mut entity_gateway = InMemoryGateway::new();
  251. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  252. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  253. for slot in 0..29 {
  254. entity_gateway.create_item(
  255. item::NewItemEntity {
  256. item: item::ItemDetail::Weapon(
  257. item::weapon::Weapon {
  258. weapon: item::weapon::WeaponType::Saber,
  259. grind: 0,
  260. special: None,
  261. attrs: [None, None, None],
  262. tekked: true,
  263. }
  264. ),
  265. location: item::ItemLocation::Inventory {
  266. character_id: char1.id,
  267. slot: slot,
  268. equipped: false,
  269. }
  270. }).await;
  271. }
  272. entity_gateway.create_item(
  273. item::NewItemEntity {
  274. item: item::ItemDetail::Tool(
  275. item::tool::Tool {
  276. tool: item::tool::ToolType::Monomate,
  277. }
  278. ),
  279. location: item::ItemLocation::Inventory {
  280. character_id: char1.id,
  281. slot: 29,
  282. equipped: false,
  283. }
  284. }).await;
  285. entity_gateway.create_item(
  286. item::NewItemEntity {
  287. item: item::ItemDetail::Tool(
  288. item::tool::Tool {
  289. tool: item::tool::ToolType::Monomate,
  290. }
  291. ),
  292. location: item::ItemLocation::Inventory {
  293. character_id: char2.id,
  294. slot: 0,
  295. equipped: false,
  296. }
  297. }).await;
  298. let mut ship = ShipServerState::new(entity_gateway.clone());
  299. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  300. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  301. join_lobby(&mut ship, ClientId(1)).await;
  302. join_lobby(&mut ship, ClientId(2)).await;
  303. create_room(&mut ship, ClientId(1), "room", "").await;
  304. join_room(&mut ship, ClientId(2), 0).await;
  305. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  306. client: 0,
  307. target: 0,
  308. unknown1: 0,
  309. area: 0,
  310. item_id: 0x210000,
  311. x: 0.0,
  312. y: 0.0,
  313. z: 0.0,
  314. })))).await.unwrap().for_each(drop);
  315. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  316. client: 0,
  317. target: 0,
  318. item_id: 0x210000,
  319. area: 0,
  320. unknown: [0; 3]
  321. })))).await.unwrap().for_each(drop);
  322. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  323. assert!(p1_inventory.count() == 30);
  324. let monomates = p1_inventory.slot(29).unwrap();
  325. assert!(monomates.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 2));
  326. }
  327. #[async_std::test]
  328. async fn test_can_not_pick_up_item_when_inventory_full() {
  329. let mut entity_gateway = InMemoryGateway::new();
  330. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  331. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  332. for slot in 0..30 {
  333. entity_gateway.create_item(
  334. item::NewItemEntity {
  335. item: item::ItemDetail::Weapon(
  336. item::weapon::Weapon {
  337. weapon: item::weapon::WeaponType::Saber,
  338. grind: 0,
  339. special: None,
  340. attrs: [None, None, None],
  341. tekked: true,
  342. }
  343. ),
  344. location: item::ItemLocation::Inventory {
  345. character_id: char1.id,
  346. slot: slot,
  347. equipped: false,
  348. }
  349. }).await;
  350. }
  351. entity_gateway.create_item(
  352. item::NewItemEntity {
  353. item: item::ItemDetail::Weapon(
  354. item::weapon::Weapon {
  355. weapon: item::weapon::WeaponType::Handgun,
  356. grind: 0,
  357. special: None,
  358. attrs: [None, None, None],
  359. tekked: true,
  360. }
  361. ),
  362. location: item::ItemLocation::Inventory {
  363. character_id: char2.id,
  364. slot: 0,
  365. equipped: false,
  366. }
  367. }).await;
  368. let mut ship = ShipServerState::new(entity_gateway.clone());
  369. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  370. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  371. join_lobby(&mut ship, ClientId(1)).await;
  372. join_lobby(&mut ship, ClientId(2)).await;
  373. create_room(&mut ship, ClientId(1), "room", "").await;
  374. join_room(&mut ship, ClientId(2), 0).await;
  375. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  376. client: 0,
  377. target: 0,
  378. unknown1: 0,
  379. area: 0,
  380. item_id: 0x210000,
  381. x: 0.0,
  382. y: 0.0,
  383. z: 0.0,
  384. })))).await.unwrap().for_each(drop);
  385. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  386. client: 0,
  387. target: 0,
  388. item_id: 0x210000,
  389. area: 0,
  390. unknown: [0; 3]
  391. })))).await.unwrap().for_each(drop);
  392. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  393. assert!(p1_inventory.count() == 30);
  394. let floor_item = ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0x210000)).unwrap();
  395. assert!(floor_item.item_id == ClientItemId(0x210000));
  396. }
  397. #[async_std::test]
  398. async fn test_can_not_drop_more_meseta_than_is_held() {
  399. let mut entity_gateway = InMemoryGateway::new();
  400. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  401. char1.meseta = 300;
  402. entity_gateway.save_character(&char1).await;
  403. let mut ship = ShipServerState::new(entity_gateway.clone());
  404. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  405. join_lobby(&mut ship, ClientId(1)).await;
  406. create_room(&mut ship, ClientId(1), "room", "").await;
  407. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
  408. client: 0,
  409. target: 0,
  410. item_id: 0xFFFFFFFF,
  411. map_area: 0,
  412. x: 0.0,
  413. z: 0.0,
  414. })))).await.unwrap().for_each(drop);
  415. let split_attempt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
  416. client: 0,
  417. target: 0,
  418. item_id: 0xFFFFFFFF,
  419. amount: 301,
  420. })))).await;
  421. assert!(split_attempt.is_err());
  422. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  423. assert!(c1.character.meseta == 300);
  424. assert!(ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0xF0000001)).is_err())
  425. }
  426. #[async_std::test]
  427. async fn test_pick_up_stack_that_would_exceed_stack_limit() {
  428. let mut entity_gateway = InMemoryGateway::new();
  429. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  430. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  431. for _ in 0..6 {
  432. entity_gateway.create_item(
  433. item::NewItemEntity {
  434. item: item::ItemDetail::Tool(
  435. item::tool::Tool {
  436. tool: item::tool::ToolType::Monomate,
  437. }
  438. ),
  439. location: item::ItemLocation::Inventory {
  440. character_id: char1.id,
  441. slot: 0,
  442. equipped: false,
  443. }
  444. }).await;
  445. }
  446. for _ in 0..6 {
  447. entity_gateway.create_item(
  448. item::NewItemEntity {
  449. item: item::ItemDetail::Tool(
  450. item::tool::Tool {
  451. tool: item::tool::ToolType::Monomate,
  452. }
  453. ),
  454. location: item::ItemLocation::Inventory {
  455. character_id: char2.id,
  456. slot: 0,
  457. equipped: false,
  458. }
  459. }).await;
  460. }
  461. let mut ship = ShipServerState::new(entity_gateway.clone());
  462. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  463. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  464. join_lobby(&mut ship, ClientId(1)).await;
  465. join_lobby(&mut ship, ClientId(2)).await;
  466. create_room(&mut ship, ClientId(1), "room", "").await;
  467. join_room(&mut ship, ClientId(2), 0).await;
  468. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
  469. client: 0,
  470. target: 0,
  471. unknown1: 0,
  472. area: 0,
  473. item_id: 0x210000,
  474. x: 0.0,
  475. y: 0.0,
  476. z: 0.0,
  477. })))).await.unwrap().for_each(drop);
  478. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  479. client: 0,
  480. target: 0,
  481. item_id: 0x210000,
  482. area: 0,
  483. unknown: [0; 3]
  484. })))).await.unwrap().for_each(drop);
  485. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  486. let monomates = p1_inventory.slot(0).unwrap();
  487. assert!(monomates.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
  488. let floor_monomates = ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0x210000)).unwrap();
  489. assert!(floor_monomates.item == FloorItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
  490. }
  491. #[async_std::test]
  492. async fn test_can_not_pick_up_meseta_when_full() {
  493. let mut entity_gateway = InMemoryGateway::new();
  494. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  495. let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  496. char1.meseta = 999999;
  497. entity_gateway.save_character(&char1).await;
  498. char2.meseta = 300;
  499. entity_gateway.save_character(&char2).await;
  500. let mut ship = ShipServerState::new(entity_gateway.clone());
  501. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  502. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  503. join_lobby(&mut ship, ClientId(1)).await;
  504. join_lobby(&mut ship, ClientId(2)).await;
  505. create_room(&mut ship, ClientId(1), "room", "").await;
  506. join_room(&mut ship, ClientId(2), 0).await;
  507. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
  508. client: 0,
  509. target: 0,
  510. item_id: 0xFFFFFFFF,
  511. map_area: 0,
  512. x: 0.0,
  513. z: 0.0,
  514. })))).await.unwrap().for_each(drop);
  515. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
  516. client: 0,
  517. target: 0,
  518. item_id: 0xFFFFFFFF,
  519. amount: 23,
  520. })))).await.unwrap().for_each(drop);
  521. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  522. client: 0,
  523. target: 0,
  524. item_id: 0xF0000001,
  525. area: 0,
  526. unknown: [0; 3]
  527. })))).await.unwrap().for_each(drop);
  528. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  529. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  530. assert!(c1.character.meseta == 999999);
  531. assert!(c2.character.meseta == 277);
  532. let floor_meseta = ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0xF0000001)).unwrap();
  533. assert!(floor_meseta.item == FloorItemType::Meseta(item::Meseta(23)));
  534. }
  535. #[async_std::test]
  536. async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
  537. let mut entity_gateway = InMemoryGateway::new();
  538. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  539. let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  540. char1.meseta = 999998;
  541. entity_gateway.save_character(&char1).await;
  542. char2.meseta = 300;
  543. entity_gateway.save_character(&char2).await;
  544. let mut ship = ShipServerState::new(entity_gateway.clone());
  545. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  546. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  547. join_lobby(&mut ship, ClientId(1)).await;
  548. join_lobby(&mut ship, ClientId(2)).await;
  549. create_room(&mut ship, ClientId(1), "room", "").await;
  550. join_room(&mut ship, ClientId(2), 0).await;
  551. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
  552. client: 0,
  553. target: 0,
  554. item_id: 0xFFFFFFFF,
  555. map_area: 0,
  556. x: 0.0,
  557. z: 0.0,
  558. })))).await.unwrap().for_each(drop);
  559. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
  560. client: 0,
  561. target: 0,
  562. item_id: 0xFFFFFFFF,
  563. amount: 23,
  564. })))).await.unwrap().for_each(drop);
  565. ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  566. client: 0,
  567. target: 0,
  568. item_id: 0xF0000001,
  569. area: 0,
  570. unknown: [0; 3]
  571. })))).await.unwrap().for_each(drop);
  572. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  573. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  574. assert!(c1.character.meseta == 999999);
  575. assert!(c2.character.meseta == 277);
  576. let floor_meseta = ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0xF0000001));
  577. assert!(floor_meseta.is_err());
  578. }
  579. #[async_std::test]
  580. async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
  581. let mut entity_gateway = InMemoryGateway::new();
  582. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
  583. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
  584. for _ in 0..5 {
  585. entity_gateway.create_item(
  586. item::NewItemEntity {
  587. item: item::ItemDetail::Tool(
  588. item::tool::Tool {
  589. tool: item::tool::ToolType::Monomate,
  590. }
  591. ),
  592. location: item::ItemLocation::Inventory {
  593. character_id: char1.id,
  594. slot: 0,
  595. equipped: false,
  596. }
  597. }).await;
  598. }
  599. let mut ship = ShipServerState::new(entity_gateway.clone());
  600. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  601. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  602. join_lobby(&mut ship, ClientId(1)).await;
  603. join_lobby(&mut ship, ClientId(2)).await;
  604. create_room(&mut ship, ClientId(1), "room", "").await;
  605. join_room(&mut ship, ClientId(2), 0).await;
  606. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
  607. client: 0,
  608. target: 0,
  609. item_id: 0x10000,
  610. map_area: 0,
  611. x: 0.0,
  612. z: 0.0,
  613. })))).await.unwrap().for_each(drop);
  614. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
  615. client: 0,
  616. target: 0,
  617. item_id: 0x10000,
  618. amount: 2,
  619. })))).await.unwrap().for_each(drop);
  620. ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
  621. client: 0,
  622. target: 0,
  623. item_id: 0xF0000001,
  624. area: 0,
  625. unknown: [0; 3]
  626. })))).await.unwrap().for_each(drop);
  627. let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
  628. assert!(p1_inventory.count() == 1);
  629. let inventory_item = p1_inventory.slot(0).unwrap();
  630. assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 3));
  631. let p2_inventory = ship.item_manager.get_character_inventory(&char2).unwrap();
  632. assert!(p2_inventory.count() == 1);
  633. let inventory_item = p2_inventory.slot(0).unwrap();
  634. assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 2));
  635. }