diff --git a/tests/test_exp_gain.rs b/tests/test_exp_gain.rs new file mode 100644 index 0000000..04b019e --- /dev/null +++ b/tests/test_exp_gain.rs @@ -0,0 +1,194 @@ +use std::time::SystemTime; + +use elseware::common::serverstate::{ClientId, ServerState}; +use elseware::entity::gateway::{EntityGateway, InMemoryGateway}; +use elseware::entity::account::{UserAccountEntity, NewUserAccountEntity, NewUserSettingsEntity}; +use elseware::entity::character::{CharacterEntity, NewCharacterEntity}; +//use elseware::entity::item::{NewItemEntity, ItemDetail, ItemLocation}; +use elseware::entity::item; +use elseware::common::leveltable::CharacterLevelTable; +use elseware::ship::ship::{ShipServerState, SendShipPacket, RecvShipPacket}; +use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType}; +use elseware::ship::monster::MonsterType; + +use libpso::packet::ship::*; +use libpso::packet::messages::*; +use libpso::packet::login::{Login, Session}; +use libpso::{utf8_to_array, utf8_to_utf16_array}; + +#[path = "common.rs"] +mod common; +use common::*; + +#[async_std::test] +async fn test_character_gains_exp() { + let mut entity_gateway = InMemoryGateway::new(); + + let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut ship = ShipServerState::new(entity_gateway.clone()); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + join_lobby(&mut ship, ClientId(1)).await; + create_room(&mut ship, ClientId(1), "room", "").await; + + let (enemy_id, exp) = { + let room = ship.rooms[0].as_ref().unwrap(); + let (enemy_id, map_enemy) = (0..).filter_map(|i| { + room.maps.enemy_by_id(i).map(|enemy| { + (i, enemy) + }).ok() + }).next().unwrap(); + let map_enemy_stats = room.monster_stats.get(&map_enemy.monster).unwrap(); + (enemy_id, map_enemy_stats.exp) + }; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{ + client: enemy_id as u8, + target: 16, + enemy_id: enemy_id as u16, + client_id: 0, + unused: 0, + last_hitter: 1, + })))).await.unwrap().for_each(drop); + + let c1 = ship.clients.get(&ClientId(1)).unwrap(); + assert!(exp == c1.character.exp); +} + +#[async_std::test] +async fn test_character_levels_up() { + let mut entity_gateway = InMemoryGateway::new(); + + let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + char1.exp = 49; + entity_gateway.save_character(&char1).await; + + let mut ship = ShipServerState::new(entity_gateway.clone()); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + join_lobby(&mut ship, ClientId(1)).await; + create_room(&mut ship, ClientId(1), "room", "").await; + + let enemy_id = { + let room = ship.rooms[0].as_ref().unwrap(); + let (enemy_id, map_enemy) = (0..).filter_map(|i| { + room.maps.enemy_by_id(i).map(|enemy| { + (i, enemy) + }).ok() + }).next().unwrap(); + enemy_id + }; + + let levelup_pkt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{ + client: enemy_id as u8, + target: 16, + enemy_id: enemy_id as u16, + client_id: 0, + unused: 0, + last_hitter: 1, + })))).await.unwrap().collect::>(); + + assert!(matches!(levelup_pkt[1].1, SendShipPacket::Message(Message {msg: GameMessage::PlayerLevelUp(PlayerLevelUp {lvl: 2, ..})}))); + + let leveltable = CharacterLevelTable::new(); + let c1 = ship.clients.get(&ClientId(1)).unwrap(); + assert!(leveltable.get_level_from_exp(c1.character.char_class, c1.character.exp) == 2); +} + +#[async_std::test] +async fn test_character_levels_up_multiple_times() { + let mut entity_gateway = InMemoryGateway::new(); + + let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut ship = ShipServerState::new(entity_gateway.clone()); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + join_lobby(&mut ship, ClientId(1)).await; + create_room(&mut ship, ClientId(1), "room", "").await; + + let (enemy_id, exp) = { + let room = ship.rooms[0].as_ref().unwrap(); + let (enemy_id, map_enemy) = (0..).filter_map(|i| { + room.maps.enemy_by_id(i).ok().and_then(|enemy| { + if enemy.monster == MonsterType::DarkFalz2 { + Some((i, enemy)) + } + else { + None + } + }) + }).next().unwrap(); + let map_enemy_stats = room.monster_stats.get(&map_enemy.monster).unwrap(); + (enemy_id, map_enemy_stats.exp) + }; + + let levelup_pkt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{ + client: enemy_id as u8, + target: 16, + enemy_id: enemy_id as u16, + client_id: 0, + unused: 0, + last_hitter: 1, + })))).await.unwrap().collect::>(); + + assert!(matches!(levelup_pkt[1].1, SendShipPacket::Message(Message {msg: GameMessage::PlayerLevelUp(PlayerLevelUp {lvl: 8, ..})}))); + + let c1 = ship.clients.get(&ClientId(1)).unwrap(); + assert!(exp == c1.character.exp); +} + +#[async_std::test] +async fn test_one_character_gets_full_exp_and_other_attacker_gets_partial() { + let mut entity_gateway = InMemoryGateway::new(); + + let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await; + + let mut ship = ShipServerState::new(entity_gateway.clone()); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + log_in_char(&mut ship, ClientId(2), "a2", "a").await; + + join_lobby(&mut ship, ClientId(1)).await; + join_lobby(&mut ship, ClientId(2)).await; + + create_room(&mut ship, ClientId(1), "room", "").await; + join_room(&mut ship, ClientId(2), 0).await; + + let (enemy_id, exp) = { + let room = ship.rooms[0].as_ref().unwrap(); + let (enemy_id, map_enemy) = (0..).filter_map(|i| { + room.maps.enemy_by_id(i).ok().and_then(|enemy| { + if enemy.monster == MonsterType::DarkFalz2 { + Some((i, enemy)) + } + else { + None + } + }) + }).next().unwrap(); + let map_enemy_stats = room.monster_stats.get(&map_enemy.monster).unwrap(); + (enemy_id, map_enemy_stats.exp) + }; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{ + client: enemy_id as u8, + target: 16, + enemy_id: enemy_id as u16, + client_id: 0, + unused: 0, + last_hitter: 1, + })))).await.unwrap().for_each(drop); + + ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{ + client: enemy_id as u8, + target: 16, + enemy_id: enemy_id as u16, + client_id: 0, + unused: 0, + last_hitter: 0, + })))).await.unwrap().for_each(drop); + + let c1 = ship.clients.get(&ClientId(1)).unwrap(); + let c2 = ship.clients.get(&ClientId(2)).unwrap(); + assert!(c1.character.exp == exp); + assert!(c2.character.exp == (exp as f32 * 0.8) as u32); +}