use std::convert::{From, Into, TryFrom, TryInto}; use crate::ship::map::Maps; #[derive(Debug)] pub enum RoomCreationError { InvalidMode, InvalidEpisode(u8), InvalidDifficulty(u8), } #[derive(Debug, Copy, Clone, derive_more::Display)] pub enum Episode { #[display(fmt="ep1")] One, #[display(fmt="ep2")] Two, #[display(fmt="ep4")] Four, } impl TryFrom for Episode { type Error = RoomCreationError; fn try_from(value: u8) -> Result { match value { 1 => Ok(Episode::One), 2 => Ok(Episode::Two), 3 => Ok(Episode::Four), _ => Err(RoomCreationError::InvalidEpisode(value)) } } } impl Into for Episode { fn into(self) -> u8 { match self { Episode::One => 1, Episode::Two => 2, Episode::Four => 3, } } } #[derive(Debug, Copy, Clone, derive_more::Display)] pub enum Difficulty { Normal, Hard, VeryHard, Ultimate, } impl TryFrom for Difficulty { type Error = RoomCreationError; fn try_from(value: u8) -> Result { match value { 0 => Ok(Difficulty::Normal), 1 => Ok(Difficulty::Hard), 2 => Ok(Difficulty::VeryHard), 3 => Ok(Difficulty::Ultimate), _ => Err(RoomCreationError::InvalidDifficulty(value)) } } } impl Into for Difficulty { fn into(self) -> u8 { match self { Difficulty::Normal => 0, Difficulty::Hard => 1, Difficulty::VeryHard => 2, Difficulty::Ultimate => 3, } } } #[derive(Debug)] pub enum RoomMode { Single { episode: Episode, difficulty: Difficulty, }, Multi { episode: Episode, difficulty: Difficulty, }, Challenge { episode: Episode, }, Battle { episode: Episode, difficulty: Difficulty, } } impl RoomMode { fn difficulty(&self) -> Difficulty { match self { RoomMode::Single {difficulty, ..} => *difficulty, RoomMode::Multi {difficulty, ..} => *difficulty, RoomMode::Battle {difficulty, ..} => *difficulty, RoomMode::Challenge {..} => Difficulty::Normal, } } fn episode(&self) -> Episode { match self { RoomMode::Single {episode, ..} => *episode, RoomMode::Multi {episode, ..} => *episode, RoomMode::Battle {episode, ..} => *episode, RoomMode::Challenge {episode, ..} => *episode, } } } #[derive(Debug)] pub struct RoomState { mode: RoomMode, pub name: String, password: [u16; 16], //pub maps: [u32; 0x20], pub maps: Maps, // drop_table // items on ground // enemy info } impl RoomState { /*fn new(mode: RoomMode) -> Room { Room { mode: mode, } }*/ pub fn from_create_room(create_room: &libpso::packet::ship::CreateRoom) -> Result { if [create_room.battle, create_room.challenge, create_room.single_player].iter().sum::() > 1 { return Err(RoomCreationError::InvalidMode) } let room_mode = if create_room.battle == 1 { RoomMode::Battle { episode: create_room.episode.try_into()?, difficulty: create_room.difficulty.try_into()?, } } else if create_room.challenge == 1 { RoomMode::Challenge { episode: create_room.episode.try_into()?, } } else if create_room.single_player == 1 { RoomMode::Single { episode: create_room.episode.try_into()?, difficulty: create_room.difficulty.try_into()?, } } else { // normal multimode RoomMode::Multi { episode: create_room.episode.try_into()?, difficulty: create_room.difficulty.try_into()?, } }; let ep = room_mode.episode(); Ok(RoomState { mode: room_mode, name: String::from_utf16_lossy(&create_room.name).trim_matches(char::from(0)).into(), password: create_room.password, //maps: [0; 0x20], maps: Maps::new(ep), }) } pub fn map_headers(&self) -> [u32; 0x20] { self.maps.map_headers() } }