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.

240 lines
8.5 KiB

/* TODO:
1. test to check if sjs/lame/limiter drop with Some() kill counter enabled
2. test to make sure other items drop with None kill counter
3. test kill counters get incremented per kill
4. test unsealing item:
- client item id does not change
- unsealed item no longer has kill counter
5. test reject unsealing item if not enough kills (can this even happen?)
*/
use elseware::common::serverstate::{ClientId, ServerState};
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
use elseware::entity::character::SectionID;
use elseware::ship::room::Difficulty;
use elseware::ship::monster::MonsterType;
use elseware::entity::item;
use libpso::packet::ship::*;
use libpso::packet::messages::*;
#[path = "common.rs"]
mod common;
use common::*;
#[async_std::test]
async fn test_item_drops_with_kill_counter() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, mut char1) = new_user_character_with_sid(&mut entity_gateway, "a1", "a", SectionID::Skyly).await;
char1.exp = 80000000;
entity_gateway.save_character(&char1).await.unwrap();
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
join_lobby(&mut ship, ClientId(1)).await;
create_ep2_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
let room = ship.blocks.0[0].rooms[0].as_mut().unwrap();
room.toggle_redbox_mode(); // enable redbox mode for sjs
let gigue_id = room.maps.get_enemy_id_by_monster_type(MonsterType::GiGue).unwrap();
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::RequestItem(RequestItem {
client: 0,
target: 0,
map_area: 9, // seaside
pt_index: 55, // gigue ? (taken from ingame logs)
enemy_id: gigue_id,
x: 0.0,
y: 0.0,
z: 0.0,
})))).await.unwrap().collect::<Vec<_>>(); // this should return 1 packet (ItemDrop)?
assert!(packets.len() == 1);
match &packets[0].1 {
SendShipPacket::Message(Message {msg: GameMessage::ItemDrop(item_drop)}) => {
assert_eq!(item_drop.item_bytes[10], 0x80)
}
_ => panic!("SJS didn't drop with the expected value! attr[2] should be 0x80 (128) for 0 kills")
}
}
#[async_std::test]
async fn test_all_equipped_kill_counters_increase_per_kill() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
let mut p1_inv = Vec::new();
p1_inv.push(entity_gateway.create_item(
item::NewItemEntity {
item: item::ItemDetail::Weapon(
item::weapon::Weapon {
weapon: item::weapon::WeaponType::SealedJSword,
grind: 0,
special: None,
attrs: [None,
None,
None,],
tekked: true,
kills: Some(0),
}
),
}).await.unwrap());
p1_inv.push(entity_gateway.create_item(
item::NewItemEntity {
item: item::ItemDetail::Unit(
item::unit::Unit {
unit: item::unit::UnitType::Limiter,
modifier: None,
kills: Some(0),
}
),
}).await.unwrap());
let equipped = item::EquippedEntity {
weapon: Some(p1_inv[0].id),
armor: None,
shield: None,
unit: [Some(p1_inv[1].id), None, None, None],
mag: None,
};
entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
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.blocks.0[0].rooms[0].as_ref().unwrap();
let enemy_id = (0..).filter_map(|i| {
room.maps.enemy_by_id(i).ok().and_then(|enemy| {
if enemy.monster == MonsterType::Booma {
Some(i)
}
else {
None
}
})
}).next().unwrap();
enemy_id
};
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::KillMonster(KillMonster{
client: enemy_id as u8,
target: 16,
map_area: 1,
data: [8,0],
})))).await.unwrap().for_each(drop);
let equipped_items = entity_gateway.get_character_equips(&char1.id).await.unwrap();
let inventory = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
let w = inventory.items.iter().find(|x| x.individual().unwrap().id == equipped_items.weapon.unwrap()).unwrap().individual().unwrap();
let u = inventory.items.iter().find(|x| x.individual().unwrap().id == equipped_items.unit[0].unwrap()).unwrap().individual().unwrap();
assert!(w.item.as_client_bytes()[11] == u.item.as_client_bytes()[11]);
}
#[async_std::test]
async fn test_non_equipped_kill_counter_does_not_increase() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
let mut p1_inv = Vec::new();
p1_inv.push(entity_gateway.create_item(
item::NewItemEntity {
item: item::ItemDetail::Weapon(
item::weapon::Weapon {
weapon: item::weapon::WeaponType::SealedJSword,
grind: 0,
special: None,
attrs: [None,
None,
None,],
tekked: true,
kills: Some(0),
}
),
}).await.unwrap());
p1_inv.push(entity_gateway.create_item(
item::NewItemEntity {
item: item::ItemDetail::Unit(
item::unit::Unit {
unit: item::unit::UnitType::Limiter,
modifier: None,
kills: Some(0),
}
),
}).await.unwrap());
let equipped = item::EquippedEntity {
weapon: Some(p1_inv[0].id),
armor: None,
shield: None,
unit: [None; 4],
mag: None,
};
entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
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.blocks.0[0].rooms[0].as_ref().unwrap();
let enemy_id = (0..).filter_map(|i| {
room.maps.enemy_by_id(i).ok().and_then(|enemy| {
if enemy.monster == MonsterType::Booma {
Some(i)
}
else {
None
}
})
}).next().unwrap();
enemy_id
};
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::KillMonster(KillMonster{
client: enemy_id as u8,
target: 16,
map_area: 1,
data: [8,0],
})))).await.unwrap().for_each(drop);
let equipped_items = entity_gateway.get_character_equips(&char1.id).await.unwrap();
let inventory = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
let w = inventory.items.iter().find(|x| x.individual().unwrap().id == equipped_items.weapon.unwrap()).unwrap().individual().unwrap();
let u = inventory.items.iter().find(|x| x.individual().unwrap().id == item::ItemEntityId(2)).unwrap().individual().unwrap();
assert!(w.item.as_client_bytes()[11] == 1);
assert!(u.item.as_client_bytes()[11] == 0);
}
// #[async_std::test]
// async fn test_kill_counter_increase_only_for_final_hit() { // don't share kills among players
// let mut entity_gateway = InMemoryGateway::default();
// let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
// }