From 2ae6711703d8ea3a5bffeaf4f1796f7e1cc49719 Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Fri, 1 May 2020 06:09:12 +0100 Subject: [PATCH] Added a `Bytes` implementation for `EffectCondition` and `DigimonProperty`. --- src/game/card/property.rs | 25 ++++ src/game/card/property/effect.rs | 2 - src/game/card/property/effect_condition.rs | 159 ++++++++++++--------- 3 files changed, 118 insertions(+), 68 deletions(-) diff --git a/src/game/card/property.rs b/src/game/card/property.rs index b7a4cf3..333ffbf 100644 --- a/src/game/card/property.rs +++ b/src/game/card/property.rs @@ -358,6 +358,31 @@ generate_enum_property_mod!( _ => "Unknown byte 0x{:x} for a digimon property", } + + impl crate::game::Bytes for Option { + type ByteArray = u8; + + type FromError = FromBytesError; + fn from_bytes(byte: &Self::ByteArray) -> Result + { + match byte { + 0 => Ok( None ), + _ => Ok( Some( DigimonProperty::from_bytes(byte)? ) ), + } + } + + type ToError = ::ToError; + #[allow(clippy::diverging_sub_expression)] // For if we ever change `CrossMoveEffect::ToError` + fn to_bytes(&self, byte: &mut Self::ByteArray) -> Result<(), Self::ToError> + { + match self { + Some(effect) => effect.to_bytes(byte)?, + None => *byte = 0, + } + + Ok(()) + } + } } ); diff --git a/src/game/card/property/effect.rs b/src/game/card/property/effect.rs index 676b1b1..bee14d4 100644 --- a/src/game/card/property/effect.rs +++ b/src/game/card/property/effect.rs @@ -453,7 +453,6 @@ impl Bytes for Effect } } -#[allow(clippy::use_self)] // False positive impl Bytes for Option { type ByteArray = [u8; 0x10]; @@ -478,7 +477,6 @@ impl Bytes for Option } type ToError = ToBytesError; - #[allow(clippy::too_many_lines)] // It's a single match, we can't really split it fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> { let bytes = util::array_split_mut!(bytes, diff --git a/src/game/card/property/effect_condition.rs b/src/game/card/property/effect_condition.rs index 26cf56a..c90da39 100644 --- a/src/game/card/property/effect_condition.rs +++ b/src/game/card/property/effect_condition.rs @@ -7,8 +7,8 @@ //! //! | Offset | Size | Type | Name | Location | Details | //! |--------|------|------------------------------|---------------------------|--------------- |------------------------------------------------------------------------------------| -//! | 0x0 | 0x0 | `bool` | Misfire | `misfire` | If the condition throws a misfire when false | -//! | 0x1 | 0x1 | `u8` | | | Always zero | +//! | 0x0 | 0x1 | `bool` | Misfire | `misfire` | If the condition throws a misfire when false | +//! | 0x1 | 0x1 | `u8` | | `unknown_1` | Always zero | //! | 0x2 | 0x1 | [`DigimonProperty`] | Property compare | `property_cmp` | The property to compare to for the condition (or 0 if the condition doesn't exist) | //! | 0x3 | 0x5 | `[u8; 0x5]` | | `unknown_3` | Unknown | //! | 0x8 | 0x1 | `DigimonProperty` | Property argument | `arg_property` | Property argument for the comparation | @@ -27,7 +27,7 @@ use crate::game::{ card::property::{ self, DigimonProperty, EffectConditionOperation }, - //util, + util, }; /// A digimon's support effect condition @@ -51,6 +51,7 @@ pub struct EffectCondition operation: EffectConditionOperation, // Unknown + unknown_1 : u8, unknown_3 : [u8; 0x5], unknown_9 : [u8; 0xb], unknown_16: [u8; 0x4], @@ -75,7 +76,87 @@ pub enum FromBytesError Operation( #[error(source)] property::effect_condition_operation::FromBytesError ), } -// Bytes +impl Bytes for EffectCondition +{ + type ByteArray = [u8; 0x20]; + + type FromError = FromBytesError; + fn from_bytes(bytes: &Self::ByteArray) -> Result + { + let bytes = util::array_split!(bytes, + misfire : 0x1, + unknown_1 : 0x1, + property_cmp: 0x1, + unknown_3 : [0x5], + arg_property: 0x1, + unknown_9 : [0xb], + arg_num : [0x2], + unknown_16 : [0x4], + operation : 1, + unknown_1b : [0x5], + ); + + Ok( Self { + misfire: (*bytes.misfire != 0), + property_cmp: DigimonProperty::from_bytes( bytes.property_cmp ) + .map_err(FromBytesError::Condition)?, + + arg_property: Option::::from_bytes( bytes.arg_property ) + .map_err(FromBytesError::PropertyArgument)?, + + arg_num: LittleEndian::read_u16( bytes.arg_num ), + + operation: EffectConditionOperation::from_bytes( bytes.operation ) + .map_err(FromBytesError::Operation)?, + + unknown_1 : *bytes.unknown_1, + unknown_3 : *bytes.unknown_3, + unknown_9 : *bytes.unknown_9, + unknown_16: *bytes.unknown_16, + unknown_1b: *bytes.unknown_1b, + }) + } + + type ToError = !; + fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> + { + let bytes = util::array_split_mut!(bytes, + misfire : 0x1, + unknown_1 : 0x1, + property_cmp: 0x1, + unknown_3 : [0x5], + arg_property: 0x1, + unknown_9 : [0xb], + arg_num : [0x2], + unknown_16 : [0x4], + operation : 1, + unknown_1b : [0x5], + ); + + // Misfire + *bytes.misfire = if self.misfire { 1 } else { 0 }; + + // Condition + self.property_cmp.to_bytes( bytes.property_cmp ).into_ok(); + + // Arguments + self.arg_property.to_bytes( bytes.arg_property ).into_ok(); + LittleEndian::write_u16(bytes.arg_num, self.arg_num); + self.operation.to_bytes(bytes.operation).into_ok(); + + // Unknowns + *bytes.unknown_1 = self.unknown_1; + *bytes.unknown_3 = self.unknown_3; + *bytes.unknown_9 = self.unknown_9; + *bytes.unknown_16 = self.unknown_16; + *bytes.unknown_1b = self.unknown_1b; + + + // And return OK + Ok(()) + } +} + impl Bytes for Option { type ByteArray = [u8; 0x20]; @@ -89,74 +170,20 @@ impl Bytes for Option } // Else build the type - Ok( Some( EffectCondition { - misfire: (bytes[0x0] != 0), - property_cmp: DigimonProperty::from_bytes( &bytes[0x2] ) - .map_err(FromBytesError::Condition)?, - - arg_property: (bytes[0x8] != 0) - .then(|| DigimonProperty::from_bytes( &bytes[0x8] )) - .transpose() - .map_err(FromBytesError::PropertyArgument)?, - - arg_num: LittleEndian::read_u16( &bytes[0x14..0x16] ), - - operation: EffectConditionOperation::from_bytes( &bytes[0x1a] ) - .map_err(FromBytesError::Operation)?, - - unknown_3: [ bytes[0x3], bytes[0x4], bytes[0x5], bytes[0x6], bytes[0x7] ], - - unknown_9: [ - bytes[0x9], bytes[0xa ], bytes[0xb ], bytes[0xc ], bytes[0xd ], bytes[0xe], - bytes[0xf], bytes[0x10], bytes[0x11], bytes[0x12], bytes[0x13] - ], - - unknown_16: [ bytes[0x16], bytes[0x17], bytes[0x18], bytes[0x19] ], - - unknown_1b: [ bytes[0x1b], bytes[0x1c], bytes[0x1d], bytes[0x1e], bytes[0x1f] ], - })) + Ok( Some( EffectCondition::from_bytes(bytes)? )) } - type ToError = !; + type ToError = ::ToError; + #[allow(clippy::diverging_sub_expression)] // For if we ever change `EffectCondition::ToError` fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> { - // If we don't exist, write a `0` on the property comparation and return - let cond = match self { - Some(cond) => cond, - None => { - bytes[0x2] = 0; - return Ok(()); - } + // Check if we exist + match self { + Some(cond) => cond.to_bytes(bytes)?, + None => bytes[0x2] = 0, }; - // 0x0 - Misfire - bytes[0x0] = if cond.misfire { 1 } else { 0 }; - - // 0x1 - Always zero - bytes[0x1] = 0; - - // 0x2 - Condition - cond.property_cmp.to_bytes(&mut bytes[0x2]).into_ok(); - - // 0x3..0x8 - Unknown[0..5] - //bytes[0x3..0x8].copy_from_slice( &self.unknown[0..5] ); - - // 0x8 - Type arg / 0 if None - if let Some(type_arg) = cond.arg_property { - type_arg.to_bytes(&mut bytes[0x8]).into_ok(); - } - else { bytes[0x8] = 0; } - - // 0x9..0x14 - Unknown[0x5..0x10] - //bytes[0x9..0x14].copy_from_slice( &self.unknown[0x5..0x10] ); - - // 0x14..0x16 - Number arg - LittleEndian::write_u16(&mut bytes[0x14..0x16], cond.arg_num); - - // 0x1a - Operation arg - cond.operation.to_bytes(&mut bytes[0x1a]).into_ok(); - - // And return OK + // And return Ok Ok(()) } }