diff --git a/src/item.rs b/src/item.rs new file mode 100644 index 0000000..cc96726 --- /dev/null +++ b/src/item.rs @@ -0,0 +1,68 @@ +use crate::{AnimationFrames, Image, mocks}; + +#[derive(Debug, Eq, PartialEq)] +pub struct Item { + pub(crate) id: String, + pub(crate) animation_frames: Vec, + pub(crate) name: Option, + pub(crate) dialogue: Option, // dialogue id +} + +impl From for Item { + fn from(string: String) -> Item { + let mut lines: Vec<&str> = string.lines().collect(); + + let id = lines[0].replace("ITM ", ""); + let mut name = None; + let mut dialogue = None; + + for _ in 0..2 { + let last_line = lines.pop().unwrap(); + + if last_line.starts_with("NAME") { + name = Some(last_line.replace("NAME ", "").to_string()); + } else if last_line.starts_with("DLG") { + dialogue = Some(last_line.replace("DLG ", "").to_string()); + } else { + lines.push(last_line); + break; + } + } + + // todo dedupe + let animation_frames = lines[1..].join(""); + let animation_frames: Vec<&str> = animation_frames.split("\n>\n").collect(); + let animation_frames: Vec = animation_frames.iter().map(|&frame| { + Image::from(frame.to_string()) + }).collect(); + + Item { id, name, animation_frames, dialogue } + } +} + +impl ToString for Item { + #[inline] + fn to_string(&self) -> String { + format!( + "ITM {}\n{}{}{}", + self.id, + self.animation_frames.to_string(), + if self.name.is_some() { format!("\nNAME {}", self.name.as_ref().unwrap()) } else { "".to_string() }, + if self.dialogue.is_some() { format!("\nDLG {}", self.dialogue.as_ref().unwrap()) } else { "".to_string() }, + ) + } +} + +#[test] +fn test_item_from_string() { + let output = Item::from(include_str!("../test/resources/item").to_string()); + let expected = mocks::item(); + assert_eq!(output, expected); +} + +#[test] +fn test_item_to_string() { + let output = mocks::item().to_string(); + let expected = include_str!("../test/resources/item").to_string(); + assert_eq!(output, expected); +} diff --git a/src/lib.rs b/src/lib.rs index e5f5060..f303e28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ pub mod colour; pub mod dialogue; pub mod palette; pub mod image; +pub mod item; pub mod mocks; pub mod position; pub mod sprite; @@ -13,6 +14,7 @@ use colour::Colour; use dialogue::Dialogue; use palette::Palette; use image::Image; +use item::Item; use position::Position; use sprite::Sprite; use tile::Tile; @@ -29,14 +31,6 @@ pub struct ExitInstance { exit: Exit, } -#[derive(Debug, Eq, PartialEq)] -pub struct Item { - id: String, - animation_frames: Vec, - name: Option, - dialogue: Option, // dialogue id -} - #[derive(Debug, Eq, PartialEq)] pub struct Exit { /// destination @@ -84,28 +78,6 @@ pub struct Game { variables: Vec, } -fn example_item() -> Item { - Item { - id: "6".to_string(), - animation_frames: vec![ - Image { - pixels: vec![ - 0,1,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,1,0,0, - 0,0,1,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,1,0, - ] - } - ], - name: Some("door".to_string()), - dialogue: Some("ITM_2".to_string()) - } -} - fn example_room() -> Room { Room { id: "a".to_string(), @@ -318,65 +290,6 @@ impl AnimationFrames for Vec { } } -impl From for Item { - fn from(string: String) -> Item { - let mut lines: Vec<&str> = string.lines().collect(); - - let id = lines[0].replace("ITM ", ""); - let mut name = None; - let mut dialogue = None; - - for _ in 0..2 { - let last_line = lines.pop().unwrap(); - - if last_line.starts_with("NAME") { - name = Some(last_line.replace("NAME ", "").to_string()); - } else if last_line.starts_with("DLG") { - dialogue = Some(last_line.replace("DLG ", "").to_string()); - } else { - lines.push(last_line); - break; - } - } - - // todo dedupe - let animation_frames = lines[1..].join(""); - let animation_frames: Vec<&str> = animation_frames.split("\n>\n").collect(); - let animation_frames: Vec = animation_frames.iter().map(|&frame| { - Image::from(frame.to_string()) - }).collect(); - - Item { id, name, animation_frames, dialogue } - } -} - -#[test] -fn test_item_from_string() { - let output = Item::from(include_str!("../test/resources/item").to_string()); - let expected = example_item(); - assert_eq!(output, expected); -} - -impl ToString for Item { - #[inline] - fn to_string(&self) -> String { - format!( - "ITM {}\n{}{}{}", - self.id, - self.animation_frames.to_string(), - if self.name.is_some() { format!("\nNAME {}", self.name.as_ref().unwrap()) } else { "".to_string() }, - if self.dialogue.is_some() { format!("\nDLG {}", self.dialogue.as_ref().unwrap()) } else { "".to_string() }, - ) - } -} - -#[test] -fn test_item_to_string() { - let output = example_item().to_string(); - let expected = include_str!("../test/resources/item").to_string(); - assert_eq!(output, expected); -} - impl From for Exit { fn from(string: String) -> Exit { // e.g. "4 3,3" diff --git a/src/mocks.rs b/src/mocks.rs index ec68e79..5364201 100644 --- a/src/mocks.rs +++ b/src/mocks.rs @@ -1,5 +1,4 @@ -use crate::{Avatar, Image, Position}; -use crate::sprite::Sprite; +use crate::{Avatar, Image, Item, Position, Sprite}; pub mod image { use crate::image::Image; @@ -94,3 +93,25 @@ pub(crate) fn sprite() -> Sprite { } } } + +pub fn item() -> Item { + Item { + id: "6".to_string(), + animation_frames: vec![ + Image { + pixels: vec![ + 0,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1,0, + ] + } + ], + name: Some("door".to_string()), + dialogue: Some("ITM_2".to_string()) + } +}