mindustry logic execution, map- and schematic- parsing and rendering
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use exoquant::{ditherer, Color, Remapper, SimpleColorSpace};
use fimg::{scale::Nearest, DynImage, Image};
use mindus::{
    block::{Rotation, SORTER},
    data::dynamic::DynData,
    item::Type::*,
    Schematic,
};
use std::process::ExitCode;
macro_rules! fail {
    () => {
        fail!("<in> (<width>x<height>)")
    };
    ($usage:literal) => {{
        eprintln!(concat!("usage: p2s ", comat::comat!($usage)));
        return ExitCode::FAILURE;
    }};
}
const ITEMS: [mindus::item::Type; 22] = [
    Copper,
    Lead,
    Metaglass,
    Graphite,
    Sand,
    Coal,
    Titanium,
    Thorium,
    Scrap,
    Silicon,
    Plastanium,
    PhaseFabric,
    SurgeAlloy,
    SporePod,
    BlastCompound,
    Pyratite,
    Beryllium,
    Tungsten,
    Oxide,
    Carbide,
    FissileMatter,
    DormantCyst,
];

fn main() -> ExitCode {
    let mut args = std::env::args().skip(1);
    let Some(input) = args.next() else {
        fail!("{bold_red}<input_file>{reset}");
    };
    let mut img = DynImage::open(input).to_rgb();
    let palette = ITEMS
        .map(|i| i.color())
        .map(|(r, g, b)| Color::new(r, g, b, 255));

    if let Some(size) = args.next() {
        let Some((w, h)) = size.split_once('x') else {
            fail!(".. <w>{bold_red}x{reset}<h>")
        };
        let Ok(w) = w.parse() else {
            fail!(".. <width: valid number>x<h>")
        };
        let Ok(h) = h.parse() else {
            fail!(".. <w>x<h: valid number>")
        };
        img = img.scale::<Nearest>(w, h);
    }

    let quant = Remapper::new(&palette, &SimpleColorSpace::default(), &ditherer::None).remap(
        &img.chunked()
            .map(|&[r, g, b]| Color::new(r, g, b, 255))
            .collect::<Vec<_>>(),
        img.width() as usize,
    );
    Image::<Box<[u8]>, 3>::build(img.width(), img.height())
        .buf(
            quant
                .iter()
                .map(|&i| ITEMS[i as usize].color())
                .flat_map(|(r, g, b)| [r, g, b])
                .collect(),
        )
        .scale::<Nearest>(img.width() * 4, img.height() * 4)
        .save("quant.png");
    let mut s = Schematic::new(img.width() as usize, img.height() as usize);
    for x in 0..img.width() as usize {
        for y in 0..img.height() as usize {
            s.set(
                x as usize,
                y as usize,
                &SORTER,
                DynData::Content(
                    mindus::content::Type::Item,
                    quant[(img.height() as usize - y - 1) * img.width() as usize + x] as u16,
                ),
                Rotation::Up,
            )
            .unwrap();
        }
    }
    clipp::copy(s.serialize_base64().unwrap());
    ExitCode::SUCCESS
}