mindustry logic execution, map- and schematic- parsing and rendering
ratios
| -rw-r--r-- | mindus/Cargo.toml | 2 | ||||
| -rw-r--r-- | mindus/build.rs | 59 | ||||
| -rw-r--r-- | mindus/src/block/distribution.rs | 4 | ||||
| -rw-r--r-- | mindus/src/block/liquid.rs | 4 | ||||
| -rw-r--r-- | mindus/src/block/mod.rs | 21 | ||||
| -rw-r--r-- | mindus/src/block/ratios.rs | 247 | ||||
| -rw-r--r-- | mindus/src/data/schematic.rs | 16 | ||||
| -rw-r--r-- | mindus/src/exe/draw.rs | 4 | ||||
| -rw-r--r-- | mindus/src/exe/map.rs | 4 | ||||
| -rw-r--r-- | mindus/src/lib.rs | 2 | ||||
| -rw-r--r-- | mindus/src/unit.rs | 8 |
11 files changed, 352 insertions, 19 deletions
diff --git a/mindus/Cargo.toml b/mindus/Cargo.toml index 35cc54a..b327f36 100644 --- a/mindus/Cargo.toml +++ b/mindus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindus" -version = "5.0.6" +version = "5.0.7" edition = "2021" description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)" authors = [ diff --git a/mindus/build.rs b/mindus/build.rs index 53a8011..4c317cd 100644 --- a/mindus/build.rs +++ b/mindus/build.rs @@ -59,20 +59,63 @@ fn main() { } for e in walkdir.into_iter().filter_map(Result::ok) { let path = e.path(); - if path.is_file() && let Some(e) = path.extension() && e == "png" { - let p = DynamicImage::from_decoder(PngDecoder::new(BufReader::new(File::open(path).unwrap())).unwrap()).unwrap(); - if path.file_name().unwrap().to_str().unwrap().contains("-liquid.png") { - continue + if path.is_file() + && let Some(e) = path.extension() + && e == "png" + { + let p = DynamicImage::from_decoder( + PngDecoder::new(BufReader::new(File::open(path).unwrap())).unwrap(), + ) + .unwrap(); + if path + .file_name() + .unwrap() + .to_str() + .unwrap() + .contains("-liquid.png") + { + continue; } let f = path.file_name().unwrap().to_str().unwrap(); - if f.contains("bottom") || f.contains("-team") || f.contains("-end") || f.contains("stack") { + if f.contains("bottom") + || f.contains("-team") + || f.contains("-end") + || f.contains("stack") + { continue; } let rgb = path.components().any(|c| c.as_os_str() == "floors"); let env = path.components().any(|c| c.as_os_str() == "environment"); - let path = kebab2bigsnek(path.with_extension("").file_name().unwrap().to_str().unwrap()); - if matches!(path.as_str(), "CLIFF_CRUSHER_ROTATOR" | "NEOPLASIA_REACTOR_CENTER" | "FLUX_REACTOR_MID" | "EDGE" | "PHASE_CONVEYOR_BRIDGE" | "BRIDGE_ARROW" | "DUCT_BRIDGE_BRIDGE" | "DUCT_BRIDGE_ARROW" | "LAUNCHPOD" | "BRIDGE_CONVEYOR_BRIDGE" | "BRIDGE_CONVEYOR_ARROW" | "PHASE_CONVEYOR_ARROW" | "REINFORCED_BRIDGE_CONDUIT_ARROW" | "REINFORCED_BRIDGE_CONDUIT_BRIDGE" | "PHASE_CONDUIT_BRIDGE" | "BRIDGE_CONDUIT_ARROW" | "PHASE_CONDUIT_ARROW" | "BRIDGE_CONDUIT_BRIDGE" | "PLATED_CONDUIT_CAP") { - continue + let path = kebab2bigsnek( + path.with_extension("") + .file_name() + .unwrap() + .to_str() + .unwrap(), + ); + if matches!( + path.as_str(), + "CLIFF_CRUSHER_ROTATOR" + | "NEOPLASIA_REACTOR_CENTER" + | "FLUX_REACTOR_MID" + | "EDGE" + | "PHASE_CONVEYOR_BRIDGE" + | "BRIDGE_ARROW" + | "DUCT_BRIDGE_BRIDGE" + | "DUCT_BRIDGE_ARROW" + | "LAUNCHPOD" + | "BRIDGE_CONVEYOR_BRIDGE" + | "BRIDGE_CONVEYOR_ARROW" + | "PHASE_CONVEYOR_ARROW" + | "REINFORCED_BRIDGE_CONDUIT_ARROW" + | "REINFORCED_BRIDGE_CONDUIT_BRIDGE" + | "PHASE_CONDUIT_BRIDGE" + | "BRIDGE_CONDUIT_ARROW" + | "PHASE_CONDUIT_ARROW" + | "BRIDGE_CONDUIT_BRIDGE" + | "PLATED_CONDUIT_CAP" + ) { + continue; } println!("do {path}"); macro_rules! writ { diff --git a/mindus/src/block/distribution.rs b/mindus/src/block/distribution.rs index 97308fe..010c5e2 100644 --- a/mindus/src/block/distribution.rs +++ b/mindus/src/block/distribution.rs @@ -197,7 +197,9 @@ impl BlockLogic for ItemBlock { s: Scale, ) -> ImageHolder<4> { let mut p = load!(from name which is ["sorter" | "inverted-sorter" | "duct-router" | "duct-unloader" | "unit-cargo-unload-point" | "unloader" | "item-source"], s); - if let Some(state) = state && let Some(item) = Self::get_state(state) { + if let Some(state) = state + && let Some(item) = Self::get_state(state) + { let mut top = load!(s -> match name { "unit-cargo-unload-point" => "unit-cargo-unload-point-top", "unloader" => "unloader-center", diff --git a/mindus/src/block/liquid.rs b/mindus/src/block/liquid.rs index 59f1946..384dc98 100644 --- a/mindus/src/block/liquid.rs +++ b/mindus/src/block/liquid.rs @@ -87,7 +87,9 @@ impl BlockLogic for FluidBlock { s: Scale, ) -> ImageHolder<4> { let mut p = load!("liquid-source", s); - if let Some(state) = state && let Some(liq) = Self::get_state(state) { + if let Some(state) = state + && let Some(liq) = Self::get_state(state) + { let mut top = load!("center", s); unsafe { p.overlay(top.tint(liq.color())) }; return p; diff --git a/mindus/src/block/mod.rs b/mindus/src/block/mod.rs index 7c1cac2..3a99c28 100644 --- a/mindus/src/block/mod.rs +++ b/mindus/src/block/mod.rs @@ -16,7 +16,7 @@ macro_rules! mods { $(pub mod $mod;)* mod all { - $(pub use crate::block::$mod::*;)* + $(#[allow(unused_imports)] pub use crate::block::$mod::*;)* pub use super::simple::BasicBlock; } } @@ -26,6 +26,7 @@ mods! { content defense distribution drills liquid logic payload power production turrets walls units } +pub mod ratios; mod simple; use simple::*; @@ -36,6 +37,15 @@ macro_rules! disp { pub(crate) enum BlockLogicEnum { $($k,)+ } + + impl ratios::Ratios for BlockLogicEnum { + fn io(&self, state: Option<&State>, name: &str) -> ratios::Io { + match self { + $(Self::$k(x) => x.io(state, name),)+ + } + } + } + #[const_trait] pub trait ConstFrom<T>: Sized { fn fro(value: T) -> Self; @@ -106,6 +116,7 @@ disp! { ProcessorLogic, PayloadBlock, LampBlock, + UnitCargoLoader, DoorBlock, } @@ -175,7 +186,7 @@ impl State { } #[enum_dispatch::enum_dispatch(BlockLogicEnum)] -pub trait BlockLogic { +pub trait BlockLogic: ratios::Ratios { /// mindustry blocks are the same width and height fn get_size(&self) -> u8; @@ -325,6 +336,10 @@ impl Block { self.name } + pub fn io(&self, state: Option<&State>) -> ratios::Io { + <BlockLogicEnum as ratios::Ratios>::io(&self.logic, state, self.name) + } + /// should you send context to [`image`]? #[must_use] #[inline] @@ -793,7 +808,7 @@ make_register! { "duct-unloader" => ItemBlock::new(1, true, cost!(Graphite: 20, Silicon: 20, Tungsten: 10)); "surge-conveyor" => StackConveyor::new(1, false, cost!(SurgeAlloy: 1, Tungsten: 1)); "surge-router" => SurgeRouter::new(1, false, cost!(SurgeAlloy: 5, Tungsten: 1)); // not symmetric - "unit-cargo-loader" -> BasicBlock::new(3, true, cost!(Silicon: 80, SurgeAlloy: 50, Oxide: 20)); + "unit-cargo-loader" -> UnitCargoLoader::new(3, true, cost!(Silicon: 80, SurgeAlloy: 50, Oxide: 20)); "unit-cargo-unload-point" => ItemBlock::new(2, true, cost!(Silicon: 60, Tungsten: 60)); "cultivator" -> ProductionBlock::new(2, true, cost!(Copper: 25, Lead: 25, Silicon: 10)); "graphite-press" -> ProductionBlock::new(2, true, cost!(Copper: 75, Lead: 30)); diff --git a/mindus/src/block/ratios.rs b/mindus/src/block/ratios.rs new file mode 100644 index 0000000..d4298eb --- /dev/null +++ b/mindus/src/block/ratios.rs @@ -0,0 +1,247 @@ +use std::borrow::Cow; +use std::collections::HashMap; + +use super::State; +use crate::unit::Type::*; +#[macro_export] +macro_rules! ratios { + ([$($input:ident: $icnt:literal),*] => [$($output:ident: $ocnt:literal),*]) => {{ + #[allow(unused_imports)] + use $crate::{fluid::Type::*, item::Type::*, block::ConstFrom}; + const I: &[($crate::block::ratios::Resource, ::std::primitive::f32)] = &[$(($crate::block::ratios::Resource::fro($input), $icnt as ::std::primitive::f32),)*]; + const O: &[($crate::block::ratios::Resource, ::std::primitive::f32)] = &[$(($crate::block::ratios::Resource::fro($output), $ocnt as ::std::primitive::f32),)*]; + $crate::block::ratios::Io::new(I, O) + }}; + [$($input:ident: $cnt:literal),*] => {{ + #[allow(unused_imports)] + use $crate::{fluid::Type::*, item::Type::*, block::ConstFrom}; + const I: &[($crate::block::ratios::Resource, ::std::primitive::f32)] = &[$(($crate::block::ratios::Resource::fro($input), $cnt as ::std::primitive::f32),)*]; + $crate::block::ratios::Io::new(I, &[][..]) + }} +} +pub use ratios; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Resource { + Item(crate::item::Type), + Fluid(crate::fluid::Type), +} + +impl const super::ConstFrom<crate::item::Type> for Resource { + fn fro(value: crate::item::Type) -> Self { + Self::Item(value) + } +} + +impl const super::ConstFrom<crate::fluid::Type> for Resource { + fn fro(value: crate::fluid::Type) -> Self { + Self::Fluid(value) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Io { + pub input: Cow<'static, [(Resource, f32)]>, + pub output: Cow<'static, [(Resource, f32)]>, +} + +impl Io { + fn none() -> Self { + Self { + input: Cow::from(&[][..]), + output: Cow::from(&[][..]), + } + } + + pub fn new(input: &'static [(Resource, f32)], output: &'static [(Resource, f32)]) -> Self { + Self { + input: Cow::from(input), + output: Cow::from(output), + } + } +} + +#[derive(Default)] +pub(crate) struct IoBuilder { + pub net: HashMap<Resource, f32>, +} + +impl std::ops::AddAssign<Io> for IoBuilder { + fn add_assign(&mut self, rhs: Io) { + for &(res, n) in &*rhs.output { + *self.net.entry(res).or_default() += n; + } + for &(res, n) in &*rhs.input { + *self.net.entry(res).or_default() -= n; + } + } +} + +impl From<IoBuilder> for Io { + fn from(value: IoBuilder) -> Self { + let (mut input, output): (Vec<_>, Vec<_>) = value + .net + .into_iter() + .filter(|(_, n)| n.abs() > 0.001) + .map(|(r, n)| (r, (n * 100.0 + 0.5).floor() / 100.0)) + .partition(|&(_, n)| n < 0.0); + input.iter_mut().for_each(|(_, v)| *v = v.abs()); + Self { + input: Cow::Owned(input), + output: Cow::Owned(output), + } + } +} + +pub trait Ratios { + #[inline] + #[must_use] + #[allow(unused_variables)] + fn io(&self, state: Option<&State>, name: &str) -> Io { + Io::none() + } +} + +macro_rules! just { + ($for:ident, [$($input:ident: $icnt:literal),*] => [$($output:ident: $ocnt:literal),*]) => { + impl Ratios for super::$for { + fn io(&self, _: Option<&State>, _: &str) -> Io { + ratios!([$($input : $icnt),*] => [$($output : $ocnt),*]) + } + } + } +} + +macro_rules! rats { + ($for:ident { $($name:literal: [$($input:ident: $icnt:literal),*] => [$($output:ident: $ocnt:literal),*])+ }) => { + impl Ratios for super::$for { + fn io(&self, _: Option<&State>, name: &str) -> Io { + $(_ = crate::data::renderer::load!($name);)+ // string validation + match name { + $($name => ratios!([$($input : $icnt),*] => [$($output : $ocnt),*]),)+ + _ => Io::none() + } + } + } + }; + ($for:ident { none }) => { + impl Ratios for super::$for {} + } +} + +rats!(ConveyorBlock { none }); +rats!(JunctionBlock { none }); +rats!(StackConveyor { none }); +rats!(BridgeBlock { none }); +rats!(ItemBlock { none }); +rats!(DuctBlock { none }); +rats!(SimpleDuctBlock { none }); +rats!(FluidBlock { none }); +rats!(SurgeRouter { none }); +rats!(ProductionBlock { + "cultivator": [Water: 18] => [SporePod: 0.6] + "graphite-press": [Coal: 1.33] => [Graphite: 0.66] + "multi-press": [Coal: 6, Water: 6] => [Graphite: 4] + "silicon-smelter": [Coal: 1.5, Sand: 3] => [Silicon: 1.5] + "silicon-crucible": [Coal: 2.66, Sand: 4, Pyratite: 0.66] => [Silicon: 5.33] + "kiln": [Lead: 2, Sand: 2] => [Metaglass: 2] + "plastanium-compressor": [Oil: 15, Titanium: 2] => [Plastanium: 1] + "phase-weaver": [Thorium: 2, Sand: 5] => [PhaseFabric: 0.5] + "surge-smelter": [Copper: 2.4, Lead: 3.2, Titanium: 1.6, Silicon: 2.4] => [SurgeAlloy: 0.8] + "cryofluid-mixer": [Titanium: 0.5, Water: 12] => [Cryofluid: 12] + "pyratite-mixer": [Coal: 0.75, Lead: 1.5, Sand: 1.5] => [Pyratite: 0.75] + "blast-mixer": [Pyratite: 0.75, SporePod: 0.75] => [BlastCompound: 0.75] + "melter": [Scrap: 6] => [Slag: 12] + "spore-press": [SporePod: 3] => [Oil: 18] + "pulverizer": [Scrap: 1.5] => [Sand: 1.5] + "coal-centrifuge": [Oil: 6] => [Coal: 2] + "silicon-arc-furnace": [Graphite: 1.2, Sand: 4.8] => [Silicon: 4.8] + "electrolyzer": [Water: 10] => [Ozone: 4, Hydrogen: 6] + "atmospheric-concentrator": [] => [Nitrogen: 4] + "carbide-crucible": [Tungsten: 0.88, Graphite: 1.33] => [Carbide: 0.44] + "cyanogen-synthesizer": [Arkycite: 40, Graphite: 0.75] => [Cyanogen: 3] + "phase-synthesizer": [Thorium: 1, Sand: 3, Ozone: 2] => [PhaseFabric: 0.5] + "vent-condenser": [] => [Water: 30] +}); +rats!(SeparatorBlock { + "separator": [Slag: 4] => [Copper: 2.15, Lead: 1.29, Graphite: 0.86, Titanium: 0.86] + "disassembler": [Slag: 7.2, Scrap: 4] => [Sand: 2, Graphite: 1, Titanium: 1, Thorium: 1] +}); +rats!(HeatConduit { none }); +rats!(HeatCrafter { + "oxidation-chamber": [Ozone: 2, Beryllium: 0.5] => [Oxide: 0.5] + "phase-heater": [PhaseFabric: 0.12] => [] +}); +rats!(WallBlock { none }); +rats!(DoorBlock { none }); +rats!(HeatedBlock { none }); // these arent erekir, btw +rats!(ConduitBlock { none }); +impl Ratios for super::UnitFactory { + fn io(&self, state: Option<&State>, name: &str) -> Io { + state.map_or(Io::none(), |s| { + Self::get_state(s).map_or(Io::none(), |t| match (name, t) { + ("ground-factory", Dagger) => ratios![Silicon: 0.66, Lead: 0.66], + ("ground-factory", Crawler) => ratios![Silicon: 0.8, Coal: 1], + ("ground-factory", Nova) => ratios![Silicon: 0.75, Lead: 0.5, Titanium: 0.5], + ("air-factory", Flare) => ratios![Silicon: 1], + ("air-factory", Mono) => ratios![Silicon: 0.85, Lead: 0.42], + ("naval-factory", Risso) => ratios![Silicon: 0.44, Metaglass: 0.77], + ("naval-factory", Retusa) => ratios![Silicon: 0.3, Metaglass: 0.5, Titanium: 0.4], + ("tank-fabricator", _) => ratios![Beryllium: 1.14, Silicon: 1.42], + ("ship-fabricator", _) => ratios![Graphite: 1.25, Silicon: 1.75], + ("mech-fabricator", _) => ratios![Beryllium: 1.25, Silicon: 1.75], + (f, t) => unreachable!("{f}, {t:?}"), + }) + }) + } +} +rats!(ConstructorBlock { + "additive-reconstructor": [Silicon: 4, Graphite: 4] => [] + "multiplicative-reconstructor": [Silicon: 4.33, Titanium: 2.66, Metaglass: 1.33] => [] + "exponential-reconstructor": [Silicon: 9.44, Titanium: 8.33, Plastanium: 7.22, Cryofluid: 60] => [] + "tetrative-reconstructor": [Silicon: 4.16, Plastanium: 2.5, SurgeAlloy: 2.08, PhaseFabric: 1.45, Cryofluid: 180] => [] + "tank-refabricator": [Hydrogen: 3, Silicon: 1.33, Titanium: 1] => [] + "mech-refabricator": [Hydrogen: 3, Silicon: 1.11, Tungsten: 0.88] => [] + "ship-refabricator": [Hydrogen: 3, Silicon: 1.2, Tungsten: 0.8] => [] + "prime-refabricator": [Nitrogen: 10, Thorium: 1.33, Silicon: 1.66] => [] +}); +rats!(BasicBlock { + "water-extractor": [] => [Water: 6.6] + "unit-repair-tower": [Ozone: 3] => [] + "oil-extractor": [Water: 9] => [] // *cough* +}); +rats!(WallDrillBlock { none }); // more cough +rats!(DrillBlock { none }); +rats!(MessageLogic { none }); +rats!(SwitchLogic { none }); +rats!(ProcessorLogic { "hyper-processor": [Cryofluid: 4.8] => [] }); +rats!(MemoryBlock { none }); +rats!(CanvasBlock { none }); +rats!(LampBlock { none }); +rats!(ConnectorBlock { none }); +rats!(DiodeBlock { none }); +just!(NuclearGeneratorBlock, [Thorium: 0.16, Cryofluid: 2.4] => []); // thoreactor +just!(ImpactReactorBlock, [BlastCompound: 0.42, Cryofluid: 15] => []); +just!(Neoplasia, [Arkycite: 80, Water: 10, PhaseFabric: 0.33] => [Neoplasm: 20]); +rats!(GeneratorBlock { + "differential-generator": [Pyratite: 1, Cryofluid: 6] => [] + "turbine-condenser": [] => [Water: 5] + "chemical-combustion-chamber": [Ozone: 2, Arkycite: 40] => [] + "pyrolysis-generator": [Slag: 20, Arkycite: 40] => [Water: 20] + "flux-reactor": [Cyanogen: 9] => [] + "rtg-generator": [Thorium: 0.07] => [] +}); +rats!(ItemTurret { none }); // eh +rats!(TractorBeamTurret { none }); +rats!(PointDefenseTurret { none }); +rats!(ContinousTurret { none }); +rats!(Turret { none }); +rats!(ShieldBlock { none }); +rats!(PayloadBlock { none }); +rats!(PayloadConveyor { none }); +rats!(SimplePayloadBlock { none }); +rats!(PayloadRouter { none }); +rats!(RadarBlock { none }); +rats!(UnitCargoLoader { "unit-cargo-loader": [Nitrogen: 10] => [] }); +rats!(AssemblerBlock { none }); +rats!(RepairTurret { none }); +rats!(AssemblerModule { none }); diff --git a/mindus/src/data/schematic.rs b/mindus/src/data/schematic.rs index 78da2bb..1b6f4d2 100644 --- a/mindus/src/data/schematic.rs +++ b/mindus/src/data/schematic.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::fmt::{self, Write}; use thiserror::Error; +use crate::block::ratios::{Io, IoBuilder}; use crate::block::{self, Block, Rotation, State, BLOCK_REGISTRY}; use crate::data::base64; use crate::data::dynamic::{self, DynData}; @@ -172,6 +173,21 @@ impl Schematic { ] } + /// Ratios of this schematic. + /// ``` + /// # use mindus::Schematic; + /// # use mindus::block::ratios::ratios; + /// assert_eq!(Schematic::deserialize_base64("bXNjaAF4nEWMSw7CMAxEh9REVSqx5hKcCLFISxaR0o9Sg8rtSTpFePPkmWfDwTWQyY8B5z75VdE9wzrkuGicJwA2+T6kFeb+aNDtym2MW8i4LJ/sNWo4dje8ksa31zmXuyv+Y4BTgRD2iIi9M+xM7WrUgnoNhYpQESpCxfKLrUo9FsISLX6vKgwhhCVK+wX5/BtM").unwrap().ratios(), + /// ratios![[Coal: 5.25, Lead: 10.5, Sand: 10.5, Water: 180] => [BlastCompound: 5.25, SporePod: 0.75]]); + /// ``` + pub fn ratios(&self) -> Io { + let mut io = IoBuilder::default(); + for p in self.blocks.iter().filter_map(|o| o.as_ref()) { + io += p.block.io(p.state.as_ref()); + } + io.into() + } + /// create a new schematic, erroring if too big /// ``` /// # use mindus::Schematic; diff --git a/mindus/src/exe/draw.rs b/mindus/src/exe/draw.rs index 1faa4d5..447bc44 100644 --- a/mindus/src/exe/draw.rs +++ b/mindus/src/exe/draw.rs @@ -24,7 +24,9 @@ pub fn main(args: Args) { } { Ok(s) => { let i = s.render(); - if let Ok(v) = std::env::var("SAVE") && v == "1" { + if let Ok(v) = std::env::var("SAVE") + && v == "1" + { i.save("x.png"); continue; } diff --git a/mindus/src/exe/map.rs b/mindus/src/exe/map.rs index 3cec055..f61ecdf 100644 --- a/mindus/src/exe/map.rs +++ b/mindus/src/exe/map.rs @@ -20,7 +20,9 @@ pub fn main(args: Args) { Err(e) => print_err!(e, "fail"), Ok(m) => { let deser_took = starting_deser.elapsed(); - if let Ok(v) = std::env::var("SAVE") && v == "1" { + if let Ok(v) = std::env::var("SAVE") + && v == "1" + { m.render().save("x.png"); continue; } diff --git a/mindus/src/lib.rs b/mindus/src/lib.rs index 535f523..1d3a310 100644 --- a/mindus/src/lib.rs +++ b/mindus/src/lib.rs @@ -1,5 +1,5 @@ //! crate for dealing with mindustry -#![feature(const_trait_impl, let_chains, effects, try_blocks, const_option)] +#![feature(generic_arg_infer, const_trait_impl, const_option, let_chains, effects)] #![allow(clippy::redundant_closure_call)] #![warn( clippy::multiple_unsafe_ops_per_block, diff --git a/mindus/src/unit.rs b/mindus/src/unit.rs index 78b70ec..b35e3a8 100644 --- a/mindus/src/unit.rs +++ b/mindus/src/unit.rs @@ -167,7 +167,9 @@ impl Controller { None }; let n = buff.read_i8()?; - let command = if let Ok(n) = u8::try_from(n) && let Ok(u) = UnitCommand::try_from(n) { + let command = if let Ok(n) = u8::try_from(n) + && let Ok(u) = UnitCommand::try_from(n) + { Some(u) } else { None @@ -363,7 +365,9 @@ fn read_status(buff: &mut DataRead) -> Result<[Status; 3], ReadError> { for i in 0..buff.read_i32()? { let this = Status::try_from(buff.read_u16()?); buff.skip(4)?; - if let Ok(s) = this && i < 3 { + if let Ok(s) = this + && i < 3 + { status[i as usize] = s; } } |