use rustc_serialize::json;
use std::io::prelude::*;
use std::fs::File;
#[derive(RustcEncodable, RustcDecodable, Clone)]
pub struct Field {
pub field_type: FieldType,
pub height: i32,
pub contained_entity_id: Option<usize>,
}
impl Field {
pub fn new(field_type: FieldType) -> Field {
Field {
field_type: field_type,
height: 0,
contained_entity_id: None,
}
}
pub fn contained_entity_id(mut self, entity_id: usize) -> Field {
self.contained_entity_id = Some(entity_id);
self
}
pub fn height(mut self, height: i32) -> Field {
self.height = height;
self
}
}
#[derive(RustcEncodable, RustcDecodable, Clone)]
pub enum FieldType {
Dirt,
Grass,
Hole,
Mud,
Quicksand,
Sand,
Stone,
StoneWall,
SwampWater,
Water,
Wood,
WoodenFence,
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct Level {
pub name: String,
pub starting_point: (usize, usize),
pub end_point: (usize, usize),
size: (usize, usize),
data: Vec<Vec<Field>>,
}
impl Level {
pub fn new(name: &str, size: (usize, usize)) -> Level {
let (width, height) = size;
Level {
name: name.to_owned(),
starting_point: (0, 0),
end_point: (0, 0),
size: (width, height),
data: vec![vec![Field::new(FieldType::Grass); height]; width],
}
}
pub fn starting_point(mut self, starting_point: (usize, usize)) -> Level {
self.starting_point = starting_point;
self
}
pub fn end_point(mut self, end_point: (usize, usize)) -> Level {
self.end_point = end_point;
self
}
pub fn set_field(&mut self, field: Field, position: (usize, usize)) {
let (x, y) = position;
let (width, height) = self.size;
assert!(x < width, "x is out of bounds");
assert!(y < height, "y is out of bounds");
self.data[x][y] = field;
}
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct Campagne {
pub title: String,
levels: Vec<Level>,
}
impl Campagne {
pub fn new(title: &str) -> Campagne {
Campagne {
title: title.to_owned(),
levels: Vec::new(),
}
}
pub fn add_level(&mut self, level: Level) {
self.levels.push(level);
}
pub fn save_to_file(&self, file_name: &str) {
let mut f = match File::create(file_name) {
Err(_) => return,
Ok(file) => file,
};
let campagne = match json::encode(self) {
Err(_) => return,
Ok(campagne) => campagne,
};
match f.write_all(campagne.as_bytes()) {
Err(_) => {}
Ok(_) => {}
};
}
pub fn load_from_file(file_name: &str) -> Result<Campagne, &str> {
let mut f = match File::open(file_name) {
Err(_) => return Err(file_name),
Ok(file) => file,
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Err(_) => return Err(file_name),
Ok(_) => {}
};
match json::decode(s.as_str()) {
Err(_) => return Err(file_name),
Ok(campagne) => Ok(campagne),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn save_and_load() {
let camp = Campagne::new("Adventure Time!");
camp.save_to_file("test.json");
let new_camp = Campagne::load_from_file("test.json").ok().unwrap();
assert_eq!(camp.title, new_camp.title);
}
#[test]
fn build_campagne() {
let mut camp = Campagne::new("Adventure Time!");
let mut level = Level::new("Hunger Game", (10, 10));
let field = Field::new(FieldType::Stone);
level.set_field(field, (0, 0));
camp.add_level(level);
}
#[test]
fn new_level() {
let mut level = Level::new("Hunger Game", (10, 10));
level = level.starting_point((1, 2)).end_point((3, 4));
assert_eq!(level.size.0, 10);
assert_eq!(level.size.1, 10);
}
#[test]
fn new_field() {
let mut field = Field::new(FieldType::WoodenFence);
field = field.contained_entity_id(23).height(2);
}
}