diff --git a/crates/save/src/lib.rs b/crates/save/src/lib.rs index 2cacd42..eb6152f 100644 --- a/crates/save/src/lib.rs +++ b/crates/save/src/lib.rs @@ -2,6 +2,7 @@ mod companion; mod glyphs; mod level; mod murals; +mod scarf; mod symbol; mod test; @@ -14,6 +15,7 @@ use std::path::{Path, PathBuf}; use binrw::{until_eof, BinRead, BinReaderExt, BinWriterExt}; use chrono::{DateTime, NaiveDateTime, Utc}; use level::Level; +use scarf::Scarf; use symbol::Symbol; use crate::companion::{CompanionSymbols, CompanionWithId, Companions}; @@ -39,6 +41,15 @@ pub enum Error { #[error("Level name was not found")] LevelNameNotFound, + #[error("Scarf already at maximum length")] + ScarfMaxLength, + + #[error("Scarf already at minimum length")] + ScarfMinLength, + + #[error("Scarf can be at most 30 long")] + ScarfTooLong, + #[error("Symbol id is out of range")] SymbolIdOutOfRange, @@ -77,7 +88,7 @@ pub struct Savefile { pub symbol: Symbol, - pub scarf_length: u32, + pub scarf_length: Scarf, #[br(count = 4)] _unknown1: Vec, diff --git a/crates/save/src/scarf.rs b/crates/save/src/scarf.rs new file mode 100644 index 0000000..96866f0 --- /dev/null +++ b/crates/save/src/scarf.rs @@ -0,0 +1,58 @@ +use core::fmt; + +use binrw::{BinRead, BinWrite}; + +use crate::{Error, Result}; + + +const MAX_LENGTH: u32 = 30; + + +#[derive(Debug, Clone, BinRead, BinWrite)] +pub struct Scarf { + #[br(assert(length <= MAX_LENGTH))] + length: u32, +} + +impl Scarf { + pub fn set_length(&mut self, length: u32) -> Result<()> { + if length > MAX_LENGTH { + return Err(Error::ScarfTooLong); + } + + self.length = length; + + Ok(()) + } + + pub fn increase_length(&mut self) -> Result<()> { + let length = self.length + 1; + if length > MAX_LENGTH { + return Err(Error::ScarfMaxLength); + } + + self.length = length; + + Ok(()) + } + + pub fn decrease_length(&mut self) -> Result<()> { + let length = self.length.checked_sub(1).ok_or(Error::ScarfMinLength)?; + + self.length = length; + + Ok(()) + } +} + +impl fmt::Display for Scarf { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.length) + } +} + +impl AsRef for Scarf { + fn as_ref(&self) -> &u32 { + &self.length + } +} diff --git a/crates/save/src/test.rs b/crates/save/src/test.rs index 4341740..7da8bef 100644 --- a/crates/save/src/test.rs +++ b/crates/save/src/test.rs @@ -17,7 +17,7 @@ fn general_info() { assert_eq!(savefile.robe_tier(), 4); assert_eq!(savefile.symbol.as_ref(), &7); - assert_eq!(savefile.scarf_length, 27); + assert_eq!(savefile.scarf_length.as_ref(), &27); assert_eq!(savefile.current_level.as_ref(), &1); assert_eq!(savefile.total_collected_symbols, 107); assert_eq!(savefile.collected_symbols, 21); diff --git a/crates/wayfarer/src/edit.rs b/crates/wayfarer/src/edit.rs index 2ecc1d5..223b852 100644 --- a/crates/wayfarer/src/edit.rs +++ b/crates/wayfarer/src/edit.rs @@ -55,7 +55,7 @@ fn edit_file(cur_savefile: &Savefile, args: &Args) -> Result { let mut savefile = cur_savefile.clone(); if let Some(val) = args.scarf_length { - savefile.scarf_length = val; + savefile.scarf_length.set_length(val)?; } if let Some(val) = &args.current_level { diff --git a/crates/wayfarer/src/tui/state.rs b/crates/wayfarer/src/tui/state.rs index 3c11ae3..3a94414 100644 --- a/crates/wayfarer/src/tui/state.rs +++ b/crates/wayfarer/src/tui/state.rs @@ -173,14 +173,7 @@ impl State { 2 => savefile.total_collected_symbols = value.parse()?, 3 => savefile.current_level.set_by_name(value)?, 4 => savefile.companions_met = value.parse()?, - 5 => { - let new_length = value.parse()?; - if new_length > 30 { - bail!("Max length exceeded"); - } - - savefile.scarf_length = new_length; - } + 5 => savefile.scarf_length.set_length(value.parse()?)?, 6 => savefile.symbol.set_by_id(value.parse()?)?, 7 => { let new_color = match value { @@ -218,11 +211,7 @@ impl State { 2 => savefile.total_collected_symbols += 1, 3 => savefile.current_level = savefile.current_level.wrapping_next(), 4 => savefile.companions_met += 1, - 5 => { - if savefile.scarf_length < 30 { - savefile.scarf_length += 1; - } - } + 5 => savefile.scarf_length.increase_length()?, 6 => savefile.symbol = savefile.symbol.wrapping_next(), 7 => { savefile.set_robe_color(match savefile.robe_color() { @@ -264,11 +253,7 @@ impl State { } 3 => savefile.current_level = savefile.current_level.wrapping_previous(), 4 => savefile.companions_met = savefile.companions_met.saturating_sub(1), - 5 => { - if savefile.scarf_length > 0 { - savefile.scarf_length = savefile.scarf_length.saturating_sub(1); - } - } + 5 => savefile.scarf_length.decrease_length()?, 6 => savefile.symbol = savefile.symbol.wrapping_previous(), 7 => { savefile.set_robe_color(match savefile.robe_color() {