don't panic

This commit is contained in:
Quaternions 2024-07-29 18:20:44 -07:00
parent e3130661f4
commit 05c8db4750
4 changed files with 121 additions and 44 deletions

View File

@ -12,6 +12,7 @@ use strafesnet_common::gameplay_modes;
#[derive(Debug)] #[derive(Debug)]
pub enum Error{ pub enum Error{
InvalidHeader(binrw::Error), InvalidHeader(binrw::Error),
InvalidMode(newtypes::gameplay_modes::ModeError),
InvalidBlockId(BlockId), InvalidBlockId(BlockId),
InvalidMeshId(model::MeshId), InvalidMeshId(model::MeshId),
InvalidModelId(model::ModelId), InvalidModelId(model::ModelId),
@ -214,7 +215,7 @@ impl<R:BinReaderExt> StreamableMap<R>{
pub(crate) fn new(mut file:crate::file::File<R>)->Result<Self,Error>{ pub(crate) fn new(mut file:crate::file::File<R>)->Result<Self,Error>{
//assume the file seek is in the right place to start reading a map header //assume the file seek is in the right place to start reading a map header
let header:MapHeader=file.as_mut().read_le().map_err(Error::InvalidHeader)?; let header:MapHeader=file.as_mut().read_le().map_err(Error::InvalidHeader)?;
let modes=header.modes.into_iter().map(Into::into).collect(); let modes=header.modes.into_iter().map(TryInto::try_into).collect::<Result<_,_>>().map_err(Error::InvalidMode)?;
let attributes=header.attributes.into_iter().map(Into::into).collect(); let attributes=header.attributes.into_iter().map(Into::into).collect();
let render_configs=header.render_configs.into_iter().map(Into::into).collect(); let render_configs=header.render_configs.into_iter().map(Into::into).collect();
let bvh=header.spacial_blocks.into_iter().map(|spacial_block| let bvh=header.spacial_blocks.into_iter().map(|spacial_block|

View File

@ -27,14 +27,25 @@ impl StageElement{
self.header&Self::FORCE!=0 self.header&Self::FORCE!=0
} }
} }
impl Into<strafesnet_common::gameplay_modes::StageElement> for StageElement{ #[derive(Debug)]
fn into(self)->strafesnet_common::gameplay_modes::StageElement{ pub enum StageElementError{
strafesnet_common::gameplay_modes::StageElement::new( InvalidBehaviour,
}
impl std::fmt::Display for StageElementError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for StageElementError{}
impl TryInto<strafesnet_common::gameplay_modes::StageElement> for StageElement{
type Error=StageElementError;
fn try_into(self)->Result<strafesnet_common::gameplay_modes::StageElement,Self::Error>{
Ok(strafesnet_common::gameplay_modes::StageElement::new(
strafesnet_common::gameplay_modes::StageId::new(self.stage_id), strafesnet_common::gameplay_modes::StageId::new(self.stage_id),
self.force(), self.force(),
self.behaviour().unwrap(), self.behaviour().ok_or(StageElementError::InvalidBehaviour)?,
self.jump_limit, self.jump_limit,
) ))
} }
} }
impl From<strafesnet_common::gameplay_modes::StageElement> for StageElement{ impl From<strafesnet_common::gameplay_modes::StageElement> for StageElement{
@ -154,19 +165,31 @@ pub struct Mode{
#[br(count=header.elements)] #[br(count=header.elements)]
pub elements:Vec<(u32,StageElement)>, pub elements:Vec<(u32,StageElement)>,
} }
impl Into<strafesnet_common::gameplay_modes::Mode> for Mode{ #[derive(Debug)]
fn into(self)->strafesnet_common::gameplay_modes::Mode{ pub enum ModeError{
strafesnet_common::gameplay_modes::Mode::new( StyleModifier(super::gameplay_style::StyleModifierError),
self.style.into(), StageElement(StageElementError),
}
impl std::fmt::Display for ModeError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for ModeError{}
impl TryInto<strafesnet_common::gameplay_modes::Mode> for Mode{
type Error=ModeError;
fn try_into(self)->Result<strafesnet_common::gameplay_modes::Mode,Self::Error>{
Ok(strafesnet_common::gameplay_modes::Mode::new(
self.style.try_into().map_err(ModeError::StyleModifier)?,
strafesnet_common::model::ModelId::new(self.start), strafesnet_common::model::ModelId::new(self.start),
self.zones.into_iter().map(|(model_id,zone)| self.zones.into_iter().map(|(model_id,zone)|
(strafesnet_common::model::ModelId::new(model_id),zone.into()) (strafesnet_common::model::ModelId::new(model_id),zone.into())
).collect(), ).collect(),
self.stages.into_iter().map(Into::into).collect(), self.stages.into_iter().map(Into::into).collect(),
self.elements.into_iter().map(|(model_id,stage_element)| self.elements.into_iter().map(|(model_id,stage_element)|
(strafesnet_common::model::ModelId::new(model_id),stage_element.into()) Ok((strafesnet_common::model::ModelId::new(model_id),stage_element.try_into()?))
).collect(), ).collect::<Result<_,_>>().map_err(ModeError::StageElement)?,
) ))
} }
} }
impl From<strafesnet_common::gameplay_modes::Mode> for Mode{ impl From<strafesnet_common::gameplay_modes::Mode> for Mode{

View File

@ -2,6 +2,16 @@ use super::common::flag;
use super::integer::{Time,Ratio64,Planar64,Planar64Vec3}; use super::integer::{Time,Ratio64,Planar64,Planar64Vec3};
pub type Controls=u32; pub type Controls=u32;
#[derive(Debug)]
pub enum ControlsError{
UnknownBits,
}
impl std::fmt::Display for ControlsError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for ControlsError{}
#[binrw::binrw] #[binrw::binrw]
#[brw(little)] #[brw(little)]
@ -34,15 +44,27 @@ impl StyleModifiers{
const LADDER:u8=1<<4; const LADDER:u8=1<<4;
const SWIM:u8=1<<5; const SWIM:u8=1<<5;
} }
impl Into<strafesnet_common::gameplay_style::StyleModifiers> for StyleModifiers{ #[derive(Debug)]
fn into(self)->strafesnet_common::gameplay_style::StyleModifiers{ pub enum StyleModifierError{
strafesnet_common::gameplay_style::StyleModifiers{ Controls(ControlsError),
//TODO: fail gracefully in binrw instead of panicing here JumpSettings(JumpSettingsError),
controls_mask:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).unwrap(), StrafeSettings(StrafeSettingsError),
controls_mask_state:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask_state).unwrap(), }
strafe:self.strafe.map(Into::into), impl std::fmt::Display for StyleModifierError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for StyleModifierError{}
impl TryInto<strafesnet_common::gameplay_style::StyleModifiers> for StyleModifiers{
type Error=StyleModifierError;
fn try_into(self)->Result<strafesnet_common::gameplay_style::StyleModifiers,Self::Error>{
Ok(strafesnet_common::gameplay_style::StyleModifiers{
controls_mask:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).ok_or(StyleModifierError::Controls(ControlsError::UnknownBits))?,
controls_mask_state:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask_state).ok_or(StyleModifierError::Controls(ControlsError::UnknownBits))?,
strafe:self.strafe.map(TryInto::try_into).transpose().map_err(StyleModifierError::StrafeSettings)?,
rocket:self.rocket.map(Into::into), rocket:self.rocket.map(Into::into),
jump:self.jump.map(Into::into), jump:self.jump.map(TryInto::try_into).transpose().map_err(StyleModifierError::JumpSettings)?,
walk:self.walk.map(Into::into), walk:self.walk.map(Into::into),
ladder:self.ladder.map(Into::into), ladder:self.ladder.map(Into::into),
swim:self.swim.map(Into::into), swim:self.swim.map(Into::into),
@ -50,7 +72,7 @@ impl Into<strafesnet_common::gameplay_style::StyleModifiers> for StyleModifiers{
hitbox:self.hitbox.into(), hitbox:self.hitbox.into(),
camera_offset:strafesnet_common::integer::Planar64Vec3::raw_array(self.camera_offset), camera_offset:strafesnet_common::integer::Planar64Vec3::raw_array(self.camera_offset),
mass:strafesnet_common::integer::Planar64::raw(self.mass), mass:strafesnet_common::integer::Planar64::raw(self.mass),
} })
} }
} }
impl From<strafesnet_common::gameplay_style::StyleModifiers> for StyleModifiers{ impl From<strafesnet_common::gameplay_style::StyleModifiers> for StyleModifiers{
@ -140,13 +162,14 @@ pub struct ControlsActivation{
controls_intersects:Controls, controls_intersects:Controls,
controls_contains:Controls, controls_contains:Controls,
} }
impl Into<strafesnet_common::gameplay_style::ControlsActivation> for ControlsActivation{ impl TryInto<strafesnet_common::gameplay_style::ControlsActivation> for ControlsActivation{
fn into(self)->strafesnet_common::gameplay_style::ControlsActivation{ type Error=ControlsError;
strafesnet_common::gameplay_style::ControlsActivation::new( fn try_into(self)->Result<strafesnet_common::gameplay_style::ControlsActivation,Self::Error>{
strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).unwrap(), Ok(strafesnet_common::gameplay_style::ControlsActivation::new(
strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).unwrap(), strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).ok_or(ControlsError::UnknownBits)?,
strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).unwrap(), strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).ok_or(ControlsError::UnknownBits)?,
) strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).ok_or(ControlsError::UnknownBits)?,
))
} }
} }
impl From<strafesnet_common::gameplay_style::ControlsActivation> for ControlsActivation{ impl From<strafesnet_common::gameplay_style::ControlsActivation> for ControlsActivation{
@ -172,14 +195,26 @@ pub struct StrafeSettings{
impl StrafeSettings{ impl StrafeSettings{
const AIR_ACCEL_LIMIT:u8=1<<0; const AIR_ACCEL_LIMIT:u8=1<<0;
} }
impl Into<strafesnet_common::gameplay_style::StrafeSettings> for StrafeSettings{ #[derive(Debug)]
fn into(self)->strafesnet_common::gameplay_style::StrafeSettings{ pub enum StrafeSettingsError{
strafesnet_common::gameplay_style::StrafeSettings::new( Ratio(super::integer::RatioError),
self.enable.into(), Controls(ControlsError),
}
impl std::fmt::Display for StrafeSettingsError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for StrafeSettingsError{}
impl TryInto<strafesnet_common::gameplay_style::StrafeSettings> for StrafeSettings{
type Error=StrafeSettingsError;
fn try_into(self)->Result<strafesnet_common::gameplay_style::StrafeSettings,Self::Error>{
Ok(strafesnet_common::gameplay_style::StrafeSettings::new(
self.enable.try_into().map_err(StrafeSettingsError::Controls)?,
strafesnet_common::integer::Planar64::raw(self.mv), strafesnet_common::integer::Planar64::raw(self.mv),
self.air_accel_limit.map(strafesnet_common::integer::Planar64::raw), self.air_accel_limit.map(strafesnet_common::integer::Planar64::raw),
self.tick_rate.into(), self.tick_rate.try_into().map_err(StrafeSettingsError::Ratio)?,
) ))
} }
} }
impl From<strafesnet_common::gameplay_style::StrafeSettings> for StrafeSettings{ impl From<strafesnet_common::gameplay_style::StrafeSettings> for StrafeSettings{
@ -243,12 +278,18 @@ impl JumpSettings{
} }
} }
} }
impl Into<strafesnet_common::gameplay_style::JumpSettings> for JumpSettings{ #[derive(Debug)]
fn into(self)->strafesnet_common::gameplay_style::JumpSettings{ pub enum JumpSettingsError{
strafesnet_common::gameplay_style::JumpSettings::new( InvalidImpulseDiscriminant,
self.impulse().unwrap(), InvalidCalculationDiscriminant,
self.calculation().unwrap(), }
) impl TryInto<strafesnet_common::gameplay_style::JumpSettings> for JumpSettings{
type Error=JumpSettingsError;
fn try_into(self)->Result<strafesnet_common::gameplay_style::JumpSettings,Self::Error>{
Ok(strafesnet_common::gameplay_style::JumpSettings::new(
self.impulse().ok_or(JumpSettingsError::InvalidImpulseDiscriminant)?,
self.calculation().ok_or(JumpSettingsError::InvalidCalculationDiscriminant)?,
))
} }
} }
impl From<strafesnet_common::gameplay_style::JumpSettings> for JumpSettings{ impl From<strafesnet_common::gameplay_style::JumpSettings> for JumpSettings{

View File

@ -6,9 +6,21 @@ pub struct Ratio64{
num:i64, num:i64,
den:u64, den:u64,
} }
impl Into<strafesnet_common::integer::Ratio64> for Ratio64{ #[derive(Debug)]
fn into(self)->strafesnet_common::integer::Ratio64{ pub enum RatioError{
strafesnet_common::integer::Ratio64::new(self.num,self.den).unwrap() ZeroDenominator,
}
impl std::fmt::Display for RatioError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for RatioError{}
impl TryInto<strafesnet_common::integer::Ratio64> for Ratio64{
type Error=RatioError;
fn try_into(self)->Result<strafesnet_common::integer::Ratio64,Self::Error>{
strafesnet_common::integer::Ratio64::new(self.num,self.den)
.ok_or(RatioError::ZeroDenominator)
} }
} }
impl From<strafesnet_common::integer::Ratio64> for Ratio64{ impl From<strafesnet_common::integer::Ratio64> for Ratio64{