diff --git a/src/main.rs b/src/main.rs index 684a034..8e742b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -129,9 +129,11 @@ fn main() -> Result<(), io::Error> { let mut app = App::new(game); loop { - if !app.do_loop(&mut terminal) { + terminal.draw(|f| app.draw(f))?; + if !app.step() { break; } + // terminal.draw(|f| app.draw(f))?; } // restore terminal diff --git a/src/ui/debug_view.rs b/src/ui/debug_view.rs index 6fbfd74..f217bf0 100644 --- a/src/ui/debug_view.rs +++ b/src/ui/debug_view.rs @@ -1,7 +1,7 @@ use crossterm::event::{read, Event, KeyCode}; use tui::{backend::Backend, Frame}; -use crate::{world::Terrain, game::Game}; +use crate::{world::Terrain, game::Game, entity::Location}; use super::{controls::Controls, DefaultLayout, status_line::StatusLine, AppStatus, guest_selection::GuestSelectionView}; @@ -11,34 +11,61 @@ enum DebugTab { Items, Map, } -pub struct DebugView<'a> { - list: Vec>, + +struct CreatureItem{ + id: u32, + name: String, + profession: String, + loc: Location +} + +struct ItemItem{ + id: u32, + name: String, + item_type: String, + owner: String, +} + +pub struct DebugView { + list: Vec, // Vec, list_state: tui::widgets::ListState, - item_list: Vec>, + item_list: Vec, // Vec, item_list_state: tui::widgets::ListState, selected: DebugTab, map_scroll: (u16, u16), } -impl<'a> DebugView<'a> { - pub fn new(game: &Game) -> DebugView<'a> { +impl DebugView { + pub fn new(game: &Game) -> DebugView { let mut list = vec![]; let mut item_list = vec![]; for (id, creature) in game.state.creatures.iter() { - list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", - id.1, creature.name, - creature.profession, - creature.loc, - ))); + list.push(CreatureItem { + id: id.1, + name: creature.name.clone(), + profession: format!("{}", creature.profession), + loc: creature.loc, + }); + // list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", + // id.1, creature.name, + // creature.profession, + // creature.loc, + // ))); } for (id, item) in game.state.items.iter() { - item_list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", - id.1, item.name, - item.item_type, - item.owner, - ))); + item_list.push(ItemItem { + id: id.1, + name: item.name.clone(), + item_type: format!("{}", item.item_type), + owner: format!("{}", item.owner), + }); + // item_list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", + // id.1, item.name, + // item.item_type, + // item.owner, + // ))); } let mut view = DebugView { @@ -141,7 +168,13 @@ impl<'a> DebugView<'a> { match data.selected { DebugTab::Creatures => { - let main_window = tui::widgets::List::new(data.list.clone()) + let main_window = tui::widgets::List::new(data.list.iter().map(|c| { + tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", + c.id, c.name, + c.profession, + c.loc, + )) + }).collect::>()) .block(tui::widgets::Block::default().title("Guests").borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .highlight_style(tui::style::Style::default().add_modifier(tui::style::Modifier::ITALIC)) @@ -149,7 +182,13 @@ impl<'a> DebugView<'a> { f.render_stateful_widget(main_window, chunks.main, &mut data.list_state); }, DebugTab::Items => { - let main_window = tui::widgets::List::new(data.item_list.clone()) + let main_window = tui::widgets::List::new(data.item_list.iter().map(|i| { + tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", + i.id, i.name, + i.item_type, + i.owner, + )) + }).collect::>()) .block(tui::widgets::Block::default().title("Items").borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .highlight_style(tui::style::Style::default().add_modifier(tui::style::Modifier::ITALIC)) diff --git a/src/ui/guest_selection.rs b/src/ui/guest_selection.rs index c1a154e..359b401 100644 --- a/src/ui/guest_selection.rs +++ b/src/ui/guest_selection.rs @@ -5,20 +5,31 @@ use crate::game::Game; use super::{AppStatus, DefaultLayout, controls::Controls, status_line::StatusLine, talk_to_guest::TalkToGuestView, debug_view::DebugView}; -pub struct GuestSelectionView<'a> { - guest_list: Vec>, +struct Guest { + name: String, + profession: String, + inventory_size: usize, +} + +pub struct GuestSelectionView { + guest_list: Vec, // tui::widgets::ListItem guest_list_state: tui::widgets::ListState, } -impl<'a> GuestSelectionView<'a> { - pub fn new(game: &Game) -> GuestSelectionView<'a> { +impl GuestSelectionView { + pub fn new(game: &Game) -> GuestSelectionView { let guest_list = game.state.guests().iter().map(|creature_id| { let creature = game.state.get_creature(*creature_id).unwrap(); - tui::widgets::ListItem::new(format!( - "{} ({}, {} items)", - creature.name, - creature.profession, game.state.get_inventory(creature.entity.id).len() - )) + Guest { + name: creature.name.clone(), + profession: format!("{}", creature.profession), + inventory_size: game.state.get_inventory(creature.entity.id).len(), + } + // tui::widgets::ListItem::new(format!( + // "{} ({}, {} items)", + // creature.name, + // creature.profession, game.state.get_inventory(creature.entity.id).len() + // )) }).collect(); let mut guest_list_state = tui::widgets::ListState::default(); guest_list_state.select(Some(0)); @@ -76,7 +87,13 @@ impl<'a> GuestSelectionView<'a> { pub fn draw(&mut self, f: &mut Frame, game: &Game) { let chunks = DefaultLayout::default(f.size()); - let main_window = tui::widgets::List::new(self.guest_list.clone()) + let main_window = tui::widgets::List::new(self.guest_list.iter().map(|guest| { + tui::widgets::ListItem::new(format!( + "{} ({}, {} items)", + guest.name, + guest.profession, guest.inventory_size + )) + }).collect::>()) .block(tui::widgets::Block::default().title("Guests").borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .highlight_style(tui::style::Style::default().add_modifier(tui::style::Modifier::ITALIC)) diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 88fa9db..1c91228 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -22,28 +22,17 @@ use self::{chat::{Chat, ChatLine}, controls::Controls, debug_view::DebugView, gu * |........................| */ -pub enum AppStatus<'a> { +pub enum AppStatus { Initial, - GuestSelection(GuestSelectionView<'a>), + GuestSelection(GuestSelectionView), TalkToGuest(TalkToGuestView), BuyFromGuest(EntityId), - Debug(DebugView<'a>), + Debug(DebugView), } -pub struct App<'a> { +pub struct App { game: Game, - status: AppStatus<'a>, - next_status: Option>, - - - // Conversation - conversation: Chat, - conversation_scroll: u16, - - // // Guest Selection - // guest_selection: Option>, - // // Debug - // debug_view: Option>, + status: AppStatus, } pub struct DefaultLayout { @@ -73,30 +62,15 @@ impl DefaultLayout { } } -impl<'a> App<'a> { - pub fn new(state: Game) -> App<'a> { +impl App { + pub fn new(state: Game) -> App { App { game: state, status: AppStatus::Initial, - conversation: Chat::new(), - conversation_scroll: 0, - next_status: None, - // guest_selection: None, - // debug_view: None, } } - pub fn do_loop(&'a mut self, terminal: &mut Terminal) -> bool { - terminal.draw(|f| self.draw(f)).unwrap(); - self.step() - } - - pub fn step(&'a mut self) -> bool { - if let Some(next_status) = self.next_status.take() { - self.status = next_status; - self.next_status = None; - } - + pub fn step(&mut self) -> bool { let mut ret = (true, None); match &mut self.status { AppStatus::Initial => { @@ -125,7 +99,9 @@ impl<'a> App<'a> { ret = debug_view.control(&mut self.game); } } - self.next_status = ret.1; + if let Some(next_status) = ret.1 { + self.status = next_status; + } ret.0 } @@ -181,51 +157,6 @@ impl<'a> App<'a> { pub fn draw_initial(&mut self, _f: &mut Frame) {} - fn draw_talk_to_guest(&self, f: &mut Frame, guest: Option) { - let chunks = DefaultLayout::default(f.size()); - - let guest = self.game.state.get_creature(guest.unwrap()).unwrap(); - - let key_style = tui::style::Style::default() - .add_modifier(tui::style::Modifier::BOLD) - .fg(tui::style::Color::Green) - .bg(tui::style::Color::Black); - - let mut full_text = self.conversation.to_spans(); - full_text.push(tui::text::Spans::from(vec![ - tui::text::Span::styled("(a) ", key_style), - tui::text::Span::raw("What's your business?"), - ])); - full_text.push(tui::text::Spans::from(vec![ - tui::text::Span::styled("(b) ", key_style), - tui::text::Span::raw("What do you have to sell?"), - ])); - full_text.push(tui::text::Spans::from(vec![ - tui::text::Span::styled("(c) ", key_style), - tui::text::Span::raw("Heard of anything interesting?"), - ])); - let text = tui::text::Text::from(full_text); - let scroll: u16 = ((text.lines.len() as u16) ) - .saturating_sub( - (chunks.main.height as u16).saturating_sub(2) // 2 lines for the border - ) - .saturating_sub(self.conversation_scroll); - - let main_window = tui::widgets::Paragraph::new(text) - .block(tui::widgets::Block::default().title(guest.name.clone()).borders(tui::widgets::Borders::ALL)) - .style(tui::style::Style::default().fg(tui::style::Color::White)) - .scroll((scroll, 0)); - - let mut binding = Controls::new(); - let controls = binding - .add("a-z".to_owned(), "Talk".to_owned()) - .add("Esc".to_owned(), "Back".to_owned()) - .render(); - - self.draw_status(f, chunks.status); - f.render_widget(main_window, chunks.main); - f.render_widget(controls, chunks.controls); - } fn draw_buy_from_guest(&self, f: &mut Frame, guest_id: EntityId) { let chunks = DefaultLayout::default(f.size()); @@ -256,42 +187,4 @@ impl<'a> App<'a> { f.render_widget(controls, chunks.controls); } - /** - * Conversation - */ - fn greet_guest(&mut self, guest_id: Option) { - let guest = self.game.state.get_creature(guest_id.unwrap()).unwrap(); - self.conversation.add_line(ChatLine::new( - (EntityType::Creature, 0), - "You".to_owned(), - "Greetings traveller!".to_owned(), - false - )); - self.conversation.add_line(ChatLine::new( - guest_id.unwrap(), - guest.name.clone(), - "Hello, I'm ".to_owned() + &guest.name + ", nice to meet you! " - + "I'm a " + &guest.profession.to_string() + ".", - false - )); - self.conversation_scroll = 0; - } - - fn ask_business(&mut self, guest: Option) { - let guest = self.game.state.get_creature(guest.unwrap()).unwrap(); - self.conversation.add_line(ChatLine::new( - (EntityType::Creature, 0), - "You".to_owned(), - "What's your business?".to_owned(), - false - )); - self.conversation.add_line(ChatLine::new( - guest.entity.id, - guest.name.clone(), - guest.say_agenda(& self.game.state), - false - )); - self.conversation_scroll = 0; - } - } \ No newline at end of file