mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/block/distribution.rs')
| -rw-r--r-- | src/block/distribution.rs | 208 |
1 files changed, 150 insertions, 58 deletions
diff --git a/src/block/distribution.rs b/src/block/distribution.rs index 08df5de..db21c17 100644 --- a/src/block/distribution.rs +++ b/src/block/distribution.rs @@ -8,53 +8,55 @@ use crate::item; make_simple!( ConveyorBlock, - |_, _, name, _, ctx: Option<&RenderingContext>| { + |_, _, name, _, ctx: Option<&RenderingContext>, rot: Rotation| { let ctx = ctx.unwrap(); // we set want_context to true - Some(tile(ctx, "distribution", "conveyors", name, ctx.rotation)) + Some(tile(ctx, "distribution", "conveyors", name, rot)) + }, + |_, _, _, buff: &mut DataRead| { + // format: + // - amount: `i32` + // - iterate amount: + // - val: `i32` + // - id = (((val >> 24) as u8) & 0xff) as u16 + // - x = (val >> 16) as u8) as f32 / 127.0 + // - y = ((val >> 8) as u8 as f32 + 128.0) / 255.0 + let amount = buff.read_i32()?; + for _ in 0..amount { + buff.skip(4)?; + } + Ok(()) }, true ); make_simple!( DuctBlock, - |_, _, name, _, ctx: Option<&RenderingContext>| { + |_, _, name, _, ctx: Option<&RenderingContext>, rot| { let ctx = ctx.unwrap(); - Some(tile(ctx, "distribution", "ducts", name, ctx.rotation)) + Some(tile(ctx, "distribution", "ducts", name, rot)) + }, + |_, _, _, buff: &mut DataRead| { + // format: + // - rec_dir: `i8` + buff.skip(1) }, true ); make_simple!( JunctionBlock, - |_, _, _, _, _| None, - |_, _, _, _, _, buff: &mut crate::data::DataRead| { - // format: - // - iterate 4 - // - u8 - // - iterate u8 - // - i64 - for _ in 0..4 { - let _ = buff.read_u8()?; - let n = buff.read_u8()? as usize; - buff.skip(n * 8)?; - } - Ok(()) - }, + |_, _, _, _, _, _| None, + |_, _, _, buff: &mut DataRead| { read_directional_item_buffer(buff) }, false ); -make_simple!( - SimpleDuctBlock, - |_, _, name, _, ctx: Option<&RenderingContext>| { - let ctx = ctx.unwrap(); - let mut base = load("distribution/ducts", "duct-base").unwrap().clone(); - let mut top = load("distribution/ducts", name).unwrap().clone(); - top.rotate(ctx.rotation.rotated(false).count()); - base.overlay(&top, 0, 0); - Some(ImageHolder::from(base)) - }, - true -); +make_simple!(SimpleDuctBlock, |_, _, name, _, _, rot: Rotation| { + let mut base = load("distribution/ducts", "duct-base").unwrap().clone(); + let mut top = load("distribution/ducts", name).unwrap().clone(); + top.rotate(rot.rotated(false).count()); + base.overlay(&top, 0, 0); + Some(ImageHolder::from(base)) +}); fn draw_stack( _: &StackConveyor, @@ -62,9 +64,10 @@ fn draw_stack( name: &str, _: Option<&State>, ctx: Option<&RenderingContext>, + rot: Rotation, ) -> Option<ImageHolder> { let ctx = ctx.unwrap(); - let mask = mask(ctx, name); + let mask = mask(ctx, rot, name); // clone to not hold lock let edge = load("distribution/stack-conveyors", &format!("{name}-edge")) .unwrap() @@ -84,32 +87,29 @@ fn draw_stack( .unwrap() .clone() }; - let empty = ctx.cross[ctx.rotation.count() as usize].map_or(true, |(v, _)| v.name != name); + let empty = ctx.cross[rot.count() as usize].map_or(true, |(v, _)| v.name != name); // mindustry says fuck this and just draws the arrow convs in schems but im better than that Some(ImageHolder::from( - if ctx.rotation.mirrored(true, true).mask() == mask && empty && name != "surge-conveyor" { + if rot.mirrored(true, true).mask() == mask && empty && name != "surge-conveyor" { // end let mut base = gimme(2); - edgify( - ctx.rotation.mirrored(true, true).rotated(false).count(), - &mut base, - ); + edgify(rot.mirrored(true, true).rotated(false).count(), &mut base); base } else if mask == B0000 && empty { // single let mut base = gimme(0); - base.rotate(ctx.rotation.rotated(false).count()); + base.rotate(rot.rotated(false).count()); edgify(5, &mut base); base } else if mask == B0000 { // input let mut base = gimme(1); - edgify(ctx.rotation.rotated(false).count(), &mut base); + edgify(rot.rotated(false).count(), &mut base); base } else { // directional let mut base = gimme(0); - let going = ctx.rotation.rotated(false).count(); + let going = rot.rotated(false).count(); base.rotate(going); for [r, i] in [[3, 0b1000], [0, 0b0100], [1, 0b0010], [2, 0b0001]] { if (mask.into_u8() & i) == 0 && (going != r || empty) { @@ -123,7 +123,15 @@ fn draw_stack( )) } -make_simple!(StackConveyor, draw_stack, true); +make_simple!( + StackConveyor, + draw_stack, + // format: + // - link: `i32` + // - cooldown: `f32` + |_, _, _, buff: &mut DataRead| { buff.skip(8) }, + true +); make_simple!(ControlBlock); make_register! { @@ -224,7 +232,8 @@ impl BlockLogic for ItemBlock { _: &str, name: &str, state: Option<&State>, - ctx: Option<&RenderingContext>, + _: Option<&RenderingContext>, + rot: Rotation, ) -> Option<ImageHolder> { let mut p = load( match name { @@ -259,13 +268,13 @@ impl BlockLogic for ItemBlock { } if matches!(name, "duct-unloader" | "duct-router") { let mut null = load("distribution/ducts", "top").unwrap().to_owned(); - null.rotate(ctx.unwrap().rotation.rotated(false).count()); + null.rotate(rot.rotated(false).count()); if name == "duct-unloader" { let mut top = load("distribution/ducts", "duct-unloader-top") .unwrap() .to_owned(); // this rotate call could be omitted if rotation == Right to save a clone - top.rotate(ctx.unwrap().rotation.rotated(false).count()); + top.rotate(rot.rotated(false).count()); null.overlay(&top, 0, 0); } p.overlay(&null, 0, 0); @@ -277,8 +286,43 @@ impl BlockLogic for ItemBlock { } } - fn want_context(&self) -> bool { - true + /// format: + /// (sorter | unloader | duct router | item source) + /// - item: `i16` as item + /// (duct-unloader/directional): + /// - tmp: `i16` + /// - if tmp != -1: item = tmp as item + /// - offset: `u16` + /// (unit-cargo-unload-point) + /// - item: `u16` as item + /// - stale: `bool` + fn read( + &self, + b: &mut Build, + _: &BlockRegistry, + _: &EntityMapping, + buff: &mut DataRead, + ) -> Result<(), DataReadError> { + match b.block.name() { + "duct-unloader" => { + let n = buff.read_i16()?; + if n != -1 { + b.state = Some(Self::create_state(item::Type::try_from(n as u16).ok())); + } + } + "unit-cargo-unload-point" => { + b.state = Some(Self::create_state( + item::Type::try_from(buff.read_u16()?).ok(), + )); + buff.skip(1)?; + } + _ => { + b.state = Some(Self::create_state( + item::Type::try_from(buff.read_u16()?).ok(), + )); + } + } + Ok(()) } } @@ -414,25 +458,29 @@ impl BlockLogic for BridgeBlock { } /// format: - /// - out: `i32` - /// - warmup: `f32` - /// - iterate `links<u8>` - /// - in+: `i32` - /// - moved: `bool` + /// (item bridge) + /// - become [`read_buffered_item_bridge`] + /// (buffered brige) + /// - become [`read_item_buffer`] + /// (mass driver) (9b) + /// - link: `i32` + /// - rotation: `f32` + /// - state: `i8` fn read( &self, - _: &str, - _: &str, + t: &mut Build, _: &super::BlockRegistry, _: &crate::data::map::EntityMapping, buff: &mut crate::data::DataRead, ) -> Result<(), crate::data::ReadError> { - buff.read_i32()?; - buff.read_f32()?; - for _ in 0..buff.read_u8()? { - buff.read_i32()?; + match t.block.name() { + "bridge-conveyor" => read_buffered_item_bridge(buff)?, + "phase-conveyor" | "phase-conduit" | "bridge-conduit" => read_item_bridge(buff)?, + "mass-driver" => buff.skip(9)?, + // no state? + "duct-bridge" | "reinforced-bridge-conduit" => {} + _ => unreachable!(), // surely no forget } - buff.read_bool()?; Ok(()) } } @@ -443,3 +491,47 @@ pub struct BridgeConvertError { pub x: i16, pub y: i16, } + +/// format; +/// - call [`read_item_bridge`] +/// - become [`read_item_buffer`] +fn read_buffered_item_bridge(buff: &mut DataRead) -> Result<(), DataReadError> { + read_item_bridge(buff)?; + read_item_buffer(buff) +} + +/// format: +/// - index: `u8` +/// - iter `u8` +/// l: `i64` +fn read_item_buffer(buff: &mut DataRead) -> Result<(), DataReadError> { + buff.skip(1)?; + let n = buff.read_u8()? as usize; + buff.skip(n * 8) +} + +/// format: +/// - link: `i32` +/// - warmup: `f32` +/// - iterate `u8` +/// - incoming: `i32` +/// - moved: `bool` +fn read_item_bridge(buff: &mut DataRead) -> Result<(), DataReadError> { + buff.skip(8)?; + let n = buff.read_u8()? as usize; + buff.skip((n * 4) + 1) +} + +/// format: +/// - iterate 4 +/// - u8 +/// - iterate u8 +/// - i64 +fn read_directional_item_buffer(buff: &mut DataRead) -> Result<(), DataReadError> { + for _ in 0..4 { + let _ = buff.read_u8()?; + let n = buff.read_u8()? as usize; + buff.skip(n * 8)?; + } + Ok(()) +} |