use crate::actor::Actor;
use crate::console::{ConsoleSettings, DrawConsole};
use crate::constants;
use crate::coord::Coord;
use crate::database::{self, Database, Value};
use crate::defs::GameRatio;
use crate::material::MaterialInfo;
use crate::tile::TileInfo;
use crate::ui::UiSettings;
use crate::{handle_error, GameResult, DATABASE};
use failure::ResultExt;
use num_traits::identities::Zero;
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::sync::Arc;
pub enum GameLoopOutcome {
DepthChanged,
WindowClosed,
QuitGame,
PlayerDead,
NoActors, None,
}
#[derive(Debug)]
pub struct GameData {
pub console_settings: ConsoleSettings,
pub ui_settings: UiSettings,
message_list: VecDeque<String>,
player: Option<Actor>,
turn: GameRatio,
tile_info_list: Vec<Arc<TileInfo>>,
tile_start_id: Option<usize>,
material_info_list: Vec<Arc<MaterialInfo>>,
material_start_id: Option<usize>,
}
impl GameData {
pub fn new() -> GameResult<GameData> {
let settings = DATABASE.read().unwrap().get_obj("settings")?;
let console_settings = ConsoleSettings::new(&settings)?;
let ui_settings = UiSettings::new(&settings)?;
let mut game_data = GameData {
console_settings,
ui_settings,
message_list: VecDeque::with_capacity(constants::MESSAGE_DEQUE_SIZE),
player: None,
turn: GameRatio::zero(),
tile_info_list: Vec::new(),
tile_start_id: None,
material_info_list: Vec::new(),
material_start_id: None,
};
game_data.init_materials()?;
game_data.init_tiles()?;
Ok(game_data)
}
pub fn add_message(&self, message: &str) {}
pub fn player(&self) -> Actor {
self.player.clone().unwrap()
}
pub fn set_player(&mut self, player: Actor) {
self.player = Some(player)
}
pub fn turn(&self) -> GameRatio {
self.turn
}
pub fn set_turn(&mut self, value: GameRatio) {
self.turn = value;
}
pub fn tile_info(&self, id: usize) -> Arc<TileInfo> {
Arc::clone(&self.tile_info_list[id - self.tile_start_id.unwrap()])
}
pub fn material_info(&self, id: usize) -> Arc<MaterialInfo> {
Arc::clone(&self.material_info_list[id - self.material_start_id.unwrap()])
}
fn init_tiles(&mut self) -> GameResult<()> {
let tiles = DATABASE.read().unwrap().get_obj("tiles")?;
let mut vec_temp: Vec<(Arc<TileInfo>, usize)> = Vec::new();
let mut min = usize::max_value();
for tile_val in tiles.values() {
if let Value::Obj(ref tile_data) = *tile_val {
let tile = Arc::new(
TileInfo::new(self, tile_data)
.context(format!("Could not load tile:\n{}", tile_data))?,
);
let id = tile_data.id();
if id < min {
min = id;
}
vec_temp.push((tile, id));
}
}
let mut vec_option: Vec<Option<Arc<TileInfo>>> = vec![None; vec_temp.len()];
for (tile, id) in vec_temp {
vec_option[id - min] = Some(tile);
}
let vec_final = vec_option.into_iter().map(|opt| opt.unwrap()).collect();
self.tile_info_list = vec_final;
self.tile_start_id = Some(min);
Ok(())
}
fn init_materials(&mut self) -> GameResult<()> {
let materials = DATABASE.read().unwrap().get_obj("materials")?;
let mut vec_temp: Vec<(Arc<MaterialInfo>, usize)> = Vec::new();
let mut min = usize::max_value();
for material_val in materials.values() {
if let Value::Obj(ref material_data) = *material_val {
let material = Arc::new(
MaterialInfo::new(self, material_data)
.context(format!("Could not load material:\n{}", material_data))?,
);
let id = material_data.id();
if id < min {
min = id;
}
vec_temp.push((material, id));
}
}
let mut vec_option: Vec<Option<Arc<MaterialInfo>>> = vec![None; vec_temp.len()];
for (material, id) in vec_temp {
vec_option[id - min] = Some(material);
}
let vec_final = vec_option.into_iter().map(|opt| opt.unwrap()).collect();
self.material_info_list = vec_final;
self.material_start_id = Some(min);
Ok(())
}
}