mindustry logic execution, map- and schematic- parsing and rendering
embed assets into the binary
bendn 2023-06-25
parent 943fe5f · commit d928daa
-rw-r--r--Cargo.toml6
-rw-r--r--build.rs63
-rw-r--r--src/data/renderer.rs20
3 files changed, 83 insertions, 6 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 65308bd..d7269c0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,6 +15,12 @@ strconv = { path = "strconv" }
image = { version = "0.24.6", features = ["png"], default-features = false }
const-str = "0.5.5"
color-hex = "0.2.0"
+zip = { version = "0.6.6", features = ["zstd"], default-features = false }
+
+[build-dependencies]
+zip = { version = "0.6.6", features = ["zstd"], default-features = false }
+walkdir = "2"
+
[[bin]]
name = "plandustry"
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..b740e86
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,63 @@
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::{Seek, Write};
+use std::iter::Iterator;
+use std::path::Path;
+use walkdir::{DirEntry, WalkDir};
+use zip::result::ZipError;
+use zip::write::FileOptions;
+
+fn zip_dir<T>(
+ it: &mut dyn Iterator<Item = DirEntry>,
+ prefix: &str,
+ writer: T,
+ method: zip::CompressionMethod,
+) -> zip::result::ZipResult<()>
+where
+ T: Write + Seek,
+{
+ let mut zip = zip::ZipWriter::new(writer);
+ let options = FileOptions::default()
+ .compression_method(method)
+ .unix_permissions(0o755);
+
+ let mut buffer = Vec::new();
+ for entry in it {
+ let path = entry.path();
+ let name = path.strip_prefix(Path::new(prefix)).unwrap();
+
+ // Write file or directory explicitly
+ // Some unzip tools unzip files with directory paths correctly, some do not!
+ if path.is_file() {
+ println!("adding file {path:?} as {name:?} ...");
+ #[allow(deprecated)]
+ zip.start_file_from_path(name, options)?;
+ let mut f = File::open(path)?;
+
+ f.read_to_end(&mut buffer)?;
+ zip.write_all(&buffer)?;
+ buffer.clear();
+ } else if !name.as_os_str().is_empty() {
+ // Only if not root! Avoids path spec / warning
+ // and mapname conversion failed error on unzip
+ println!("adding dir {path:?} as {name:?} ...");
+ #[allow(deprecated)]
+ zip.add_directory_from_path(name, options)?;
+ }
+ }
+ zip.finish()?;
+ Result::Ok(())
+}
+
+fn main() -> Result<(), ZipError> {
+ let walkdir = WalkDir::new("assets");
+ let it = walkdir.into_iter();
+ println!("cargo:rerun-if-changed=assets/");
+ println!("cargo:rerun-if-changed=build.rs");
+ zip_dir(
+ &mut it.filter_map(|e| e.ok()),
+ "assets",
+ File::create(std::env::var("OUT_DIR").unwrap() + "/asset").unwrap(),
+ zip::CompressionMethod::Zstd,
+ )
+}
diff --git a/src/data/renderer.rs b/src/data/renderer.rs
index 3a7713b..4f81b17 100644
--- a/src/data/renderer.rs
+++ b/src/data/renderer.rs
@@ -1,20 +1,31 @@
-use std::io::BufReader;
+use std::io::{BufReader, Cursor};
use std::path::Path;
use image::codecs::png::PngDecoder;
use image::imageops::overlay;
use image::{DynamicImage, RgbaImage};
+use zip::ZipArchive;
use super::schematic::Schematic;
pub fn load(category: &str, name: &str) -> Option<RgbaImage> {
- let mut p = Path::new("assets/blocks").join(category).join(name);
+ let mut p = Path::new("target/out/blocks").join(category).join(name);
p.set_extension("png");
let f = std::fs::File::open(p).ok()?;
let r = PngDecoder::new(BufReader::new(f)).unwrap();
Some(DynamicImage::from_decoder(r).unwrap().into_rgba8())
}
+fn load_zip() {
+ if !Path::new("target/out").exists() {
+ let mut zip = ZipArchive::new(Cursor::new(
+ include_bytes!(concat!(env!("OUT_DIR"), "/asset")).to_vec(),
+ ))
+ .unwrap();
+ zip.extract("target/out").unwrap();
+ }
+}
+
const SUFFIXES: &[&str; 8] = &[
"bottom", "mid", "", "-base", "-left", "-right", "-top", "-over",
];
@@ -24,10 +35,6 @@ where
{
let mut c = RgbaImage::new(size.into() * 32, size.into() * 32);
for suffix in SUFFIXES {
- let mut p = Path::new("assets/blocks")
- .join(category)
- .join(format!("{name}{suffix}"));
- p.set_extension("png");
if let Some(p) = load(category, &format!("{name}{suffix}")) {
image::imageops::overlay(&mut c, &p, 0, 0);
}
@@ -38,6 +45,7 @@ where
pub struct Renderer {}
impl<'l> Renderer {
pub fn render(s: &'l Schematic<'_>) -> RgbaImage {
+ load_zip();
let mut canvas = RgbaImage::new((s.width * 32).into(), (s.height * 32).into());
for tile in s.block_iter() {
let mut x = tile.pos.0 as i64;