//! The `msg` crate contains the core functionality for //! the on screen message. use std::time::{Duration, Instant}; use crate::player_input::PlayerInput; /// Duration between each character printed const DURATION_PER: Duration = Duration::from_millis(100); #[derive(Debug, Clone)] pub struct Message { text: Option>, end: usize, waiting: bool, last: Instant, } impl Message { /// Returns the default empty message pub fn empty() -> Self { Self { text: None, end: 0, waiting: false, last: Instant::now(), } } /// Sets string as the current onscreen message pub fn set_message(&mut self, msg: &str) { let bytes = msg.bytes().collect(); self.text = Some(bytes); self.end = 0; } /// Attempts to update the message on screen. /// Returns true if a character was printed pub fn update(&mut self, input: PlayerInput) -> bool { let Some(text) = &self.text else { return false }; if self.end >= text.len() { if input.interact { self.text = None; } return false; } if self.waiting && !input.interact { return false; } if self.last.elapsed() < DURATION_PER { return false; } self.last = Instant::now(); if text[self.end] == b'.' { self.waiting = true; } self.end += 1; true } /// Returns the current ascii message (if exists) pub fn current(&self) -> Option<&[u8]> { self.text.as_ref().map(|text| &text[..self.end]) } /// Returns if the message box is visible pub const fn visible(&self) -> bool { self.text.is_some() } }