Compare commits
62 Commits
a26fbe1c68
...
7219481aa2
Author | SHA1 | Date | |
---|---|---|---|
7219481aa2 | |||
95b0760e6a | |||
ee8c80f42f | |||
b80e308cf2 | |||
0cd92fd4ac | |||
286b728441 | |||
919d509c3a | |||
be5c3ff633 | |||
3babc6f4bd | |||
8f72c6074b | |||
2771f5692a | |||
fae1ffe55b | |||
5976030970 | |||
9c878ed484 | |||
b0b34b6616 | |||
ff072ca026 | |||
2775f81cc9 | |||
5f4325429e | |||
6bacdd4fe3 | |||
eb9fdb485b | |||
d3d8d766b8 | |||
5be796cb5c | |||
4e88f684c5 | |||
657dabca27 | |||
6306120692 | |||
95195d07e4 | |||
b473af7680 | |||
cf09433df2 | |||
7807cf2b27 | |||
03df819a04 | |||
4ccdf579bd | |||
94c50c011d | |||
bd35481c28 | |||
1f7086396e | |||
646f75d00d | |||
9a2d1945af | |||
bd6b8effcd | |||
8c403f0d0e | |||
810d8269af | |||
acdf960d4b | |||
b8de2ea8e6 | |||
1eae3795af | |||
eac0a31056 | |||
5d6f9deb59 | |||
da0c75fa39 | |||
916bb31671 | |||
e58aff7042 | |||
3d51b3ee57 | |||
da066a3445 | |||
7aa4a6394f | |||
bdfcb5c0ad | |||
3c8a35de83 | |||
e337852d72 | |||
bc702375d2 | |||
cbb5c1fffd | |||
a2e78014ee | |||
4e1c6300d4 | |||
9417105359 | |||
9638181261 | |||
74e54935ad | |||
4202ef8ff7 | |||
e349a41b16 |
@ -3,6 +3,7 @@ use serde::{Serialize, Deserialize};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
use crate::ship::room::Episode;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum MapArea {
|
||||
@ -256,6 +257,60 @@ impl MapArea {
|
||||
MapArea::SaintMillion => Episode::Four,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> &str{
|
||||
match self {
|
||||
MapArea::Pioneer2Ep1 => "Pioneer 2",
|
||||
MapArea::Forest1 => "Forest 1",
|
||||
MapArea::Forest2 => "Forest 2",
|
||||
MapArea::Caves1 => "Caves 1",
|
||||
MapArea::Caves2 => "Caves 2",
|
||||
MapArea::Caves3 => "Caves 3",
|
||||
MapArea::Mines1 => "Mines 1",
|
||||
MapArea::Mines2 => "Mines 2",
|
||||
MapArea::Ruins1 => "Ruins 1",
|
||||
MapArea::Ruins2 => "Ruins 2",
|
||||
MapArea::Ruins3 => "Ruins 3",
|
||||
MapArea::Dragon => "Dragon",
|
||||
MapArea::DeRolLe => "De Rol Le",
|
||||
MapArea::VolOpt => "Vol Opt",
|
||||
MapArea::DarkFalz => "Dark Falz",
|
||||
MapArea::Pioneer2Ep2 => "Pioneer 2",
|
||||
MapArea::VrTempleAlpha => "Vr Temple Alpha",
|
||||
MapArea::VrTempleBeta => "Vr Temple Beta",
|
||||
MapArea::VrSpaceshipAlpha => "Vr Spaceship Alpha",
|
||||
MapArea::VrSpaceshipBeta => "Vr Spaceship Beta",
|
||||
MapArea::Cca => "CCA",
|
||||
MapArea::JungleAreaNorth => "Jungle Area North",
|
||||
MapArea::JungleAreaEast => "Jungle Area East",
|
||||
MapArea::Mountain => "Mountain",
|
||||
MapArea::Seaside => "Seaside",
|
||||
MapArea::SeabedUpper => "Seabed Upper",
|
||||
MapArea::SeabedLower => "Seabed Lower",
|
||||
MapArea::GalGryphon => "Gal Gryphon",
|
||||
MapArea::OlgaFlow => "Olga Flow",
|
||||
MapArea::BarbaRay => "Barba Ray",
|
||||
MapArea::GolDragon => "Gol Dragon",
|
||||
MapArea::SeasideNight => "Seaside Night",
|
||||
MapArea::Tower => "Tower",
|
||||
MapArea::Pioneer2Ep4 => "Pioneer 2",
|
||||
MapArea::CraterEast => "Crater East",
|
||||
MapArea::CraterWest => "Crater West",
|
||||
MapArea::CraterSouth => "Crater South",
|
||||
MapArea::CraterNorth => "Crater North",
|
||||
MapArea::CraterInterior => "Crater Interior",
|
||||
MapArea::SubDesert1 => "Sub Desert 1",
|
||||
MapArea::SubDesert2 => "Sub Desert 2",
|
||||
MapArea::SubDesert3 => "Sub Desert 3",
|
||||
MapArea::SaintMillion => "Saint Million",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MapArea {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.as_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,11 +3,11 @@ use crate::common::serverstate::ClientId;
|
||||
use crate::common::leveltable::CharacterLevelTable;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms};
|
||||
use crate::ship::character::{FullCharacterBytesBuilder};
|
||||
use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError};
|
||||
//use crate::ship::items::;
|
||||
use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId};
|
||||
use crate::ship::packet;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::ship::map::MapArea;
|
||||
|
||||
// this function needs a better home
|
||||
pub fn block_selected(id: ClientId,
|
||||
@ -129,3 +129,30 @@ pub fn remove_from_lobby(id: ClientId,
|
||||
(n.client, leave_lobby_pkt.clone())
|
||||
}).collect())
|
||||
}
|
||||
|
||||
pub fn get_room_tab_info(id: ClientId,
|
||||
pkt: &MenuDetail,
|
||||
client_location: &mut ClientLocation,
|
||||
clients: &Clients,
|
||||
rooms: &mut Rooms)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||
let room_id = RoomId(pkt.item as usize);
|
||||
if let Some(_room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? {
|
||||
let mut room_info = String::new();
|
||||
let clients_in_room = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
for client in clients_in_room {
|
||||
let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?;
|
||||
let gc = cs.user.guildcard;
|
||||
let name = &cs.character.name;
|
||||
let cc = cs.character.char_class;
|
||||
let leveltable = CharacterLevelTable::default();
|
||||
let lv = leveltable.get_level_from_exp(cc, cs.character.exp);
|
||||
let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1);
|
||||
|
||||
room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cc,floor).as_str();
|
||||
}
|
||||
Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new(room_info)))])
|
||||
} else {
|
||||
Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new("Game is no longer active".into())))])
|
||||
}
|
||||
}
|
||||
|
@ -86,62 +86,66 @@ pub fn join_room(id: ClientId,
|
||||
-> Result<Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp);
|
||||
let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do
|
||||
// let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do
|
||||
if let Some(room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? {
|
||||
|
||||
match room.mode.difficulty() {
|
||||
room::Difficulty::Ultimate => {
|
||||
if level < 80 {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter()))
|
||||
}
|
||||
},
|
||||
room::Difficulty::VeryHard => {
|
||||
if level < 40 {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter()))
|
||||
}
|
||||
},
|
||||
room::Difficulty::Hard => {
|
||||
if level < 20 {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter()))
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
match room.mode.difficulty() {
|
||||
room::Difficulty::Ultimate => {
|
||||
if level < 80 {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter()))
|
||||
}
|
||||
},
|
||||
room::Difficulty::VeryHard => {
|
||||
if level < 40 {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter()))
|
||||
}
|
||||
},
|
||||
room::Difficulty::Hard => {
|
||||
if level < 20 {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter()))
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
|
||||
let original_area = client_location.get_area(id).unwrap();
|
||||
let original_neighbors = client_location.get_client_neighbors(id).unwrap();
|
||||
if room.bursting {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter()))
|
||||
let original_area = client_location.get_area(id).unwrap();
|
||||
let original_neighbors = client_location.get_client_neighbors(id).unwrap();
|
||||
if room.bursting {
|
||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter()))
|
||||
}
|
||||
let room_id = RoomId(pkt.item as usize);
|
||||
let original_room_clients = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever
|
||||
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
item_state.add_character_to_room(room_id, &client.character, area_client);
|
||||
|
||||
let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let join_room = builder::room::join_room(id, clients, client_location, room_id, room)?;
|
||||
let add_to = builder::room::add_to_room(id, client, &area_client, &leader, item_state, level_table, room_id)?;
|
||||
|
||||
let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap();
|
||||
room.bursting = true;
|
||||
|
||||
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
||||
vec![(id, SendShipPacket::JoinRoom(join_room))]
|
||||
.into_iter()
|
||||
.chain(original_room_clients.into_iter()
|
||||
.map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone())))
|
||||
));
|
||||
|
||||
if let Ok(leader) = client_location.get_area_leader(original_area) {
|
||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||
result = Box::new(result.chain(original_neighbors.into_iter()
|
||||
.map(move |c| (c.client, leave_lobby.clone()))))
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Game is no longer active".into())))].into_iter()))
|
||||
}
|
||||
let room_id = RoomId(pkt.item as usize);
|
||||
let original_room_clients = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever
|
||||
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
item_state.add_character_to_room(room_id, &client.character, area_client);
|
||||
|
||||
let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let join_room = builder::room::join_room(id, clients, client_location, room_id, room)?;
|
||||
let add_to = builder::room::add_to_room(id, client, &area_client, &leader, item_state, level_table, room_id)?;
|
||||
|
||||
let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap();
|
||||
room.bursting = true;
|
||||
|
||||
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
||||
vec![(id, SendShipPacket::JoinRoom(join_room))]
|
||||
.into_iter()
|
||||
.chain(original_room_clients.into_iter()
|
||||
.map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone())))
|
||||
));
|
||||
|
||||
if let Ok(leader) = client_location.get_area_leader(original_area) {
|
||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||
result = Box::new(result.chain(original_neighbors.into_iter()
|
||||
.map(move |c| (c.client, leave_lobby.clone()))))
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn done_bursting(id: ClientId,
|
||||
|
@ -205,6 +205,7 @@ pub enum SendShipPacket {
|
||||
DirectMessage(DirectMessage),
|
||||
PlayerChat(PlayerChat),
|
||||
SmallDialog(SmallDialog),
|
||||
SmallLeftDialog(SmallLeftDialog),
|
||||
JoinRoom(JoinRoom),
|
||||
AddToRoom(AddToRoom),
|
||||
LeaveLobby(LeaveLobby),
|
||||
@ -246,6 +247,7 @@ impl SendServerPacket for SendShipPacket {
|
||||
SendShipPacket::DirectMessage(pkt) => pkt.as_bytes(),
|
||||
SendShipPacket::PlayerChat(pkt) => pkt.as_bytes(),
|
||||
SendShipPacket::SmallDialog(pkt) => pkt.as_bytes(),
|
||||
SendShipPacket::SmallLeftDialog(pkt) => pkt.as_bytes(),
|
||||
SendShipPacket::JoinRoom(pkt) => pkt.as_bytes(),
|
||||
SendShipPacket::AddToRoom(pkt) => pkt.as_bytes(),
|
||||
SendShipPacket::LeaveLobby(pkt) => pkt.as_bytes(),
|
||||
@ -665,9 +667,9 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
||||
let block = self.blocks.with_client(id, &self.clients)?;
|
||||
handler::quest::player_chose_quest(id, questmenuselect, &mut self.clients, &block.client_location, &mut block.rooms)?
|
||||
},
|
||||
RecvShipPacket::MenuDetail(_menudetail) => {
|
||||
//unreachable!();
|
||||
Box::new(Vec::new().into_iter())
|
||||
RecvShipPacket::MenuDetail(menudetail) => {
|
||||
let block = self.blocks.with_client(id, &self.clients)?;
|
||||
Box::new(handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients, &mut block.rooms)?.into_iter())
|
||||
},
|
||||
RecvShipPacket::RoomPasswordReq(room_password_req) => {
|
||||
let block = self.blocks.with_client(id, &self.clients)?;
|
||||
|
@ -156,4 +156,71 @@ async fn test_set_invalid_quest_group() {
|
||||
},
|
||||
_ => panic!("Wrong quest category"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_get_room_info() {
|
||||
let mut entity_gateway = InMemoryGateway::default();
|
||||
let (_user1, mut _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
|
||||
_char1.name = String::from("GODmar");
|
||||
entity_gateway.save_character(&_char1).await.unwrap();
|
||||
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build());
|
||||
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;
|
||||
let _expectedmsg = String::from("1 Lv1 GODmar\nHUmar Pioneer 2\n");
|
||||
let packets = ship.handle(ClientId(2), &RecvShipPacket::MenuDetail(MenuDetail{menu: 3, item: 0})).await.unwrap().collect::<Vec<_>>();
|
||||
assert!(matches!(&packets[0], (ClientId(2), SendShipPacket::SmallLeftDialog(SmallLeftDialog{
|
||||
padding: [17664, 1157645568],
|
||||
msg: _expectedmsg,
|
||||
}))));
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_cannot_get_room_info_after_room_is_closed() {
|
||||
let mut entity_gateway = InMemoryGateway::default();
|
||||
let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
|
||||
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build());
|
||||
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;
|
||||
leave_room(&mut ship, ClientId(1)).await;
|
||||
let _expectedmsg = String::from("Game is no longer active!\0");
|
||||
let packets = ship.handle(ClientId(2), &RecvShipPacket::MenuDetail(MenuDetail{menu: 3, item: 0})).await.unwrap().collect::<Vec<_>>();
|
||||
assert!(matches!(&packets[0], (ClientId(2), SendShipPacket::SmallLeftDialog(SmallLeftDialog{
|
||||
padding: [17664, 1157645568],
|
||||
msg: _expectedmsg,
|
||||
}))));
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_cannot_join_room_after_its_closed() {
|
||||
let mut entity_gateway = InMemoryGateway::default();
|
||||
let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
|
||||
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build());
|
||||
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;
|
||||
leave_room(&mut ship, ClientId(1)).await;
|
||||
let _expectedmsg = String::from("This room no longer exists!\0");
|
||||
let packets = ship.handle(ClientId(2), &RecvShipPacket::MenuSelect(MenuSelect{menu: 3, item: 0})).await.unwrap().collect::<Vec<_>>();
|
||||
assert!(matches!(&packets[0], (ClientId(2), SendShipPacket::SmallDialog(SmallDialog{
|
||||
padding: [0,0],
|
||||
msg: _expectedmsg, // wow yes cool rust is so great literally the best i can't put a String::from() directly in here.
|
||||
}))));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user