diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index a2b0df0..f544ec5 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -296,11 +296,22 @@ impl From for Wormhole{ #[binrw::binrw] #[brw(little)] pub struct GeneralAttributes{ + pub header:u8, + #[br(if(header&Self::BOOSTER!=0))] pub booster:Option, + #[br(if(header&Self::TRAJECTORY!=0))] pub trajectory:Option, + #[br(if(header&Self::WORMHOLE!=0))] pub wormhole:Option, + #[br(if(header&Self::ACCELERATOR!=0))] pub accelerator:Option, } +impl GeneralAttributes{ + const BOOSTER:u8=1<<0; + const TRAJECTORY:u8=1<<1; + const WORMHOLE:u8=1<<2; + const ACCELERATOR:u8=1<<3; +} impl Into for GeneralAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::GeneralAttributes{ strafesnet_common::gameplay_attributes::GeneralAttributes{ @@ -313,7 +324,13 @@ impl Into for General } impl From for GeneralAttributes{ fn from(value:strafesnet_common::gameplay_attributes::GeneralAttributes)->Self{ + let header= + value.booster.is_some() as u8&GeneralAttributes::BOOSTER + |value.trajectory.is_some() as u8&GeneralAttributes::TRAJECTORY + |value.wormhole.is_some() as u8&GeneralAttributes::WORMHOLE + |value.accelerator.is_some() as u8&GeneralAttributes::ACCELERATOR; Self{ + header, booster:value.booster.map(Into::into), trajectory:value.trajectory.map(Into::into), wormhole:value.wormhole.map(Into::into), @@ -325,8 +342,13 @@ impl From for General #[binrw::binrw] #[brw(little)] pub struct ContactingAttributes{ + pub header:u8, + #[br(if(header&Self::CONTACTING_BEHAVIOUR!=0))] pub contact_behaviour:Option, } +impl ContactingAttributes{ + const CONTACTING_BEHAVIOUR:u8=1<<0; +} impl Into for ContactingAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::ContactingAttributes{ strafesnet_common::gameplay_attributes::ContactingAttributes{ @@ -337,6 +359,7 @@ impl Into for Cont impl From for ContactingAttributes{ fn from(value:strafesnet_common::gameplay_attributes::ContactingAttributes)->Self{ Self{ + header:value.contact_behaviour.is_some() as u8&ContactingAttributes::CONTACTING_BEHAVIOUR, contact_behaviour:value.contact_behaviour.map(Into::into), } } @@ -345,8 +368,13 @@ impl From for Cont #[binrw::binrw] #[brw(little)] pub struct IntersectingAttributes{ + pub header:u8, + #[br(if(header&Self::INTERSECTING_WATER!=0))] pub water:Option, } +impl IntersectingAttributes{ + const INTERSECTING_WATER:u8=1<<0; +} impl Into for IntersectingAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::IntersectingAttributes{ strafesnet_common::gameplay_attributes::IntersectingAttributes{ @@ -357,6 +385,7 @@ impl Into for In impl From for IntersectingAttributes{ fn from(value:strafesnet_common::gameplay_attributes::IntersectingAttributes)->Self{ Self{ + header:value.water.is_some() as u8&IntersectingAttributes::INTERSECTING_WATER, water:value.water.map(Into::into), } } diff --git a/src/newtypes/gameplay_modes.rs b/src/newtypes/gameplay_modes.rs index a6118fe..12e1e8e 100644 --- a/src/newtypes/gameplay_modes.rs +++ b/src/newtypes/gameplay_modes.rs @@ -1,65 +1,58 @@ -#[binrw::binrw] -#[brw(little,repr=u8)] -pub enum StageElementBehaviour{ - SpawnAt,//must be standing on top to get effect. except cancollide false - Trigger, - Teleport, - Platform, - //Check(point) acts like a trigger if you haven't hit all the checkpoints on previous stages yet. - //Note that all stage elements act like this, this is just the isolated behaviour. - Check, - Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both. -} -impl Into for StageElementBehaviour{ - fn into(self)->strafesnet_common::gameplay_modes::StageElementBehaviour{ - match self{ - StageElementBehaviour::SpawnAt=>strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt, - StageElementBehaviour::Trigger=>strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger, - StageElementBehaviour::Teleport=>strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport, - StageElementBehaviour::Platform=>strafesnet_common::gameplay_modes::StageElementBehaviour::Platform, - StageElementBehaviour::Check=>strafesnet_common::gameplay_modes::StageElementBehaviour::Check, - StageElementBehaviour::Checkpoint=>strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint, - } - } -} -impl From for StageElementBehaviour{ - fn from(value:strafesnet_common::gameplay_modes::StageElementBehaviour)->Self{ - match value{ - strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt=>StageElementBehaviour::SpawnAt, - strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger=>StageElementBehaviour::Trigger, - strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport=>StageElementBehaviour::Teleport, - strafesnet_common::gameplay_modes::StageElementBehaviour::Platform=>StageElementBehaviour::Platform, - strafesnet_common::gameplay_modes::StageElementBehaviour::Check=>StageElementBehaviour::Check, - strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint=>StageElementBehaviour::Checkpoint, - } - } -} - #[binrw::binrw] #[brw(little)] pub struct StageElement{ - pub stage_id:u32,//which stage spawn to send to - pub behaviour:StageElementBehaviour, + pub header:u8, + pub stage_id:u32, + #[br(if(header&Self::JUMP_LIMIT!=0))] pub jump_limit:Option, - pub force:super::common::Boolio,//allow setting to lower spawn id i.e. 7->3 +} +impl StageElement{ + const BEHAVIOUR:u8=0b00111; + const JUMP_LIMIT:u8=1<<3; + const FORCE:u8=1<<4; + const fn behaviour(&self)->Option{ + match self.header&Self::BEHAVIOUR{ + 0=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt), + 1=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger), + 2=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport), + 3=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Platform), + 4=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Check), + 5=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint), + _=>None, + } + } + const fn force(&self)->bool{ + self.header&Self::FORCE!=0 + } } impl Into for StageElement{ fn into(self)->strafesnet_common::gameplay_modes::StageElement{ strafesnet_common::gameplay_modes::StageElement::new( strafesnet_common::gameplay_modes::StageId::new(self.stage_id), - self.force.into(), - self.behaviour.into(), + self.force(), + self.behaviour().unwrap(), self.jump_limit, ) } } impl From for StageElement{ fn from(value:strafesnet_common::gameplay_modes::StageElement)->Self{ + let behaviour=match value.behaviour(){ + strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt=>0, + strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger=>1, + strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport=>2, + strafesnet_common::gameplay_modes::StageElementBehaviour::Platform=>3, + strafesnet_common::gameplay_modes::StageElementBehaviour::Check=>4, + strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint=>5, + }; + let header= + behaviour + |value.jump_limit().is_some() as u8&StageElement::JUMP_LIMIT + |value.force() as u8&StageElement::FORCE; Self{ + header, stage_id:value.stage_id().get(), - behaviour:value.behaviour().into(), jump_limit:value.jump_limit(), - force:value.force().into(), } } } diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs index 1983a22..e68ad69 100644 --- a/src/newtypes/gameplay_style.rs +++ b/src/newtypes/gameplay_style.rs @@ -5,19 +5,34 @@ pub type Controls=u32; #[binrw::binrw] #[brw(little)] pub struct StyleModifiers{ + pub header:u8, pub controls_mask:Controls, pub controls_mask_state:Controls, + #[br(if(header&Self::STRAFE!=0))] pub strafe:Option, + #[br(if(header&Self::ROCKET!=0))] pub rocket:Option, + #[br(if(header&Self::JUMP!=0))] pub jump:Option, + #[br(if(header&Self::WALK!=0))] pub walk:Option, + #[br(if(header&Self::LADDER!=0))] pub ladder:Option, + #[br(if(header&Self::SWIM!=0))] pub swim:Option, pub gravity:Planar64Vec3, pub hitbox:Hitbox, pub camera_offset:Planar64Vec3, pub mass:Planar64, } +impl StyleModifiers{ + const STRAFE:u8=1<<0; + const ROCKET:u8=1<<1; + const JUMP:u8=1<<2; + const WALK:u8=1<<3; + const LADDER:u8=1<<4; + const SWIM:u8=1<<5; +} impl Into for StyleModifiers{ fn into(self)->strafesnet_common::gameplay_style::StyleModifiers{ strafesnet_common::gameplay_style::StyleModifiers{ @@ -39,7 +54,15 @@ impl Into for StyleModifiers{ } impl From for StyleModifiers{ fn from(value:strafesnet_common::gameplay_style::StyleModifiers)->Self{ + let header= + value.strafe.is_some() as u8&StyleModifiers::STRAFE + |value.rocket.is_some() as u8&StyleModifiers::ROCKET + |value.jump.is_some() as u8&StyleModifiers::JUMP + |value.walk.is_some() as u8&StyleModifiers::WALK + |value.ladder.is_some() as u8&StyleModifiers::LADDER + |value.swim.is_some() as u8&StyleModifiers::SWIM; Self{ + header, controls_mask:value.controls_mask.bits(), controls_mask_state:value.controls_mask_state.bits(), strafe:value.strafe.map(Into::into), @@ -82,8 +105,7 @@ impl From for JumpCalculatio } } -#[binrw::binrw] -#[brw(little)] +//TODO: test this pub enum JumpImpulse{ FromTime(Time), FromHeight(Planar64), @@ -140,11 +162,16 @@ impl From for ControlsAct #[binrw::binrw] #[brw(little)] pub struct StrafeSettings{ + header:u8, enable:ControlsActivation, mv:Planar64, + #[br(if(header&Self::AIR_ACCEL_LIMIT!=0))] air_accel_limit:Option, tick_rate:Ratio64, } +impl StrafeSettings{ + const AIR_ACCEL_LIMIT:u8=1<<0; +} impl Into for StrafeSettings{ fn into(self)->strafesnet_common::gameplay_style::StrafeSettings{ strafesnet_common::gameplay_style::StrafeSettings::new( @@ -158,7 +185,9 @@ impl Into for StrafeSettings{ impl From for StrafeSettings{ fn from(value:strafesnet_common::gameplay_style::StrafeSettings)->Self{ let (enable,mv,air_accel_limit,tick_rate)=value.into_inner(); + let header=air_accel_limit.is_some() as u8&StrafeSettings::AIR_ACCEL_LIMIT; Self{ + header, enable:enable.into(), mv:mv.get(), air_accel_limit:air_accel_limit.map(|a|a.get()), @@ -190,23 +219,58 @@ impl From for PropulsionS #[binrw::binrw] #[brw(little)] pub struct JumpSettings{ - impulse:JumpImpulse, - calculation:JumpCalculation, + header:u8, + impulse:i64, +} +impl JumpSettings{ + const IMPULSE:u8=0b0011; + const CALCULATION:u8=0b1100; + const fn impulse(&self)->Option{ + match self.header&Self::IMPULSE{ + 0=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromTime(strafesnet_common::integer::Time::raw(self.impulse))), + 1=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromHeight(strafesnet_common::integer::Planar64::raw(self.impulse))), + 2=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(strafesnet_common::integer::Planar64::raw(self.impulse))), + 3=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(strafesnet_common::integer::Planar64::raw(self.impulse))), + _=>None, + } + } + const fn calculation(&self)->Option{ + match (self.header&Self::CALCULATION)>>2{ + 0=>Some(strafesnet_common::gameplay_style::JumpCalculation::Capped), + 1=>Some(strafesnet_common::gameplay_style::JumpCalculation::Energy), + 2=>Some(strafesnet_common::gameplay_style::JumpCalculation::Linear), + _=>None, + } + } } impl Into for JumpSettings{ fn into(self)->strafesnet_common::gameplay_style::JumpSettings{ strafesnet_common::gameplay_style::JumpSettings::new( - self.impulse.into(), - self.calculation.into(), + self.impulse().unwrap(), + self.calculation().unwrap(), ) } } impl From for JumpSettings{ fn from(value:strafesnet_common::gameplay_style::JumpSettings)->Self{ - let (impulse,calculation)=value.into_inner(); + let (impulse_enum,calculation)=value.into_inner(); + let (impulse,impulse_header)=match impulse_enum{ + strafesnet_common::gameplay_style::JumpImpulse::FromTime(impulse)=>(impulse.get(),0), + strafesnet_common::gameplay_style::JumpImpulse::FromHeight(impulse)=>(impulse.get(),1), + strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(impulse)=>(impulse.get(),2), + strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(impulse)=>(impulse.get(),3), + }; + let calculation_header=match calculation{ + strafesnet_common::gameplay_style::JumpCalculation::Capped=>0, + strafesnet_common::gameplay_style::JumpCalculation::Energy=>1, + strafesnet_common::gameplay_style::JumpCalculation::Linear=>2, + }; + let header= + impulse_header + |(calculation_header<<2); Self{ - impulse:impulse.into(), - calculation:calculation.into(), + header, + impulse, } } } diff --git a/src/newtypes/model.rs b/src/newtypes/model.rs index 4d42aa9..e8eb657 100644 --- a/src/newtypes/model.rs +++ b/src/newtypes/model.rs @@ -60,8 +60,13 @@ impl From for PolygonGroup{ #[binrw::binrw] #[brw(little)] pub struct RenderConfig{ + pub header:u8, + #[br(if(header&Self::TEXTURE!=0))] pub texture:Option, } +impl RenderConfig{ + const TEXTURE:u8=1<<0; +} impl Into for RenderConfig{ fn into(self)->strafesnet_common::model::RenderConfig{ strafesnet_common::model::RenderConfig{ @@ -71,7 +76,9 @@ impl Into for RenderConfig{ } impl From for RenderConfig{ fn from(value:strafesnet_common::model::RenderConfig)->Self{ + let header=value.texture.is_some() as u8&RenderConfig::TEXTURE; Self{ + header, texture:value.texture.map(|texture_id|texture_id.get()), } }