Add TGM output

Vars are now a LinkedHashMap to preserve order in the case that they
aren't alphabetized in the input.
This commit is contained in:
Tad Hardesty 2017-10-20 17:57:09 -07:00
parent cdadc8c5ba
commit 90f8c87ddc
5 changed files with 111 additions and 8 deletions

7
Cargo.lock generated
View file

@ -110,6 +110,11 @@ name = "libc"
version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "linked-hash-map"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "matrixmultiply"
version = "0.1.13"
@ -124,6 +129,7 @@ version = "0.1.0"
dependencies = [
"flame 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ndarray 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
"petgraph 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"png 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -339,6 +345,7 @@ dependencies = [
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148"
"checksum linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2aab0478615bb586559b0114d94dd8eca4fdbb73b443adcb0d00b61692b4bf"
"checksum matrixmultiply 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7ce012d2c43046267a74283eaa7e9a51941479901e2b86702be10f27e2779158"
"checksum ndarray 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "61f6cb6e2d51afc73d17e19ca3e711b6bd0221773867dbd6453698612d7af95f"
"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6"

View file

@ -10,6 +10,7 @@ png = "0.11.0"
inflate = "0.3.3"
ndarray = "0.10.11"
rand = "0.3.17"
linked-hash-map = "0.5.0"
flame = { version = "0.2.0", optional = true }
[dev-dependencies]

View file

@ -1,13 +1,16 @@
use std::collections::BTreeMap;
use std::path::Path;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::{self, BufReader, BufWriter};
use std::fmt;
use ndarray::{self, Array3, Axis};
use linked_hash_map::LinkedHashMap;
#[derive(Debug)]
pub struct Map {
pub key_length: u8,
// sorted order
pub dictionary: BTreeMap<u32, Vec<Prefab>>,
pub grid: Array3<u32>, // Z/Y/X order
}
@ -17,8 +20,8 @@ pub type Grid<'a> = ndarray::ArrayBase<ndarray::ViewRepr<&'a u32>, ndarray::Dim<
#[derive(Debug, Default)]
pub struct Prefab {
pub path: String,
// important that this is a BTreeMap, so it's ordered alphabetically
pub vars: BTreeMap<String, String>,
// insertion order, sort of most of the time alphabetical but not quite
pub vars: LinkedHashMap<String, String>,
}
impl Map {
@ -26,13 +29,18 @@ impl Map {
flame!("Map::from_file");
let mut map = Map {
key_length: 0,
dictionary: BTreeMap::new(),
dictionary: Default::default(),
grid: Array3::default((1, 255, 255)),
};
parse_map(&mut map, File::open(path)?)?;
Ok(map)
}
pub fn to_file(&self, path: &Path) -> io::Result<()> {
// DMM saver later
save_tgm(self, File::create(path)?)
}
#[inline]
pub fn dim_z(&self) -> usize {
self.grid.dim().0
@ -42,6 +50,90 @@ impl Map {
pub fn z_level(&self, z: usize) -> Grid {
self.grid.subview(Axis(0), z)
}
#[inline]
pub fn format_key(&self, key: u32) -> FormatKey {
FormatKey(self.key_length, key)
}
}
// ----------------------------------------------------------------------------
// Map Writer
#[derive(Copy, Clone)]
pub struct FormatKey(u8, u32);
impl FormatKey {
#[inline]
pub fn new(key_length: u8, key: u32) -> FormatKey {
FormatKey(key_length, key)
}
}
impl fmt::Display for FormatKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::fmt::Write;
let FormatKey(key_length, key) = *self;
if key >= 52u32.pow(key_length as u32) {
panic!(); // TODO be more reasonable
}
let mut current = 52usize.pow(key_length as u32 - 1);
for i in 0..key_length {
f.write_char(BASE_52[(key as usize / current) % 52] as char)?;
current /= 52;
}
Ok(())
}
}
const BASE_52: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const TGM_HEADER: &str = "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE";
fn save_tgm(map: &Map, f: File) -> io::Result<()> {
use std::io::Write;
let mut f = BufWriter::new(f);
write!(f, "{}\n", TGM_HEADER)?;
// dictionary
for (&key, prefabs) in map.dictionary.iter() {
write!(f, "\"{}\" = (\n", map.format_key(key))?;
for (i, fab) in prefabs.iter().enumerate() {
write!(f, "{}", fab.path)?;
if !fab.vars.is_empty() {
write!(f, "{{")?;
for (i, (var, value)) in fab.vars.iter().enumerate() {
write!(f, "\n\t{} = {}", var, value)?;
if i + 1 != fab.vars.len() {
write!(f, ";")?;
}
}
write!(f, "\n\t}}")?;
}
if i + 1 != prefabs.len() {
write!(f, ",\n")?;
}
}
write!(f, ")\n")?;
}
// grid in Y-major
for (z, z_grid) in map.grid.axis_iter(Axis(0)).enumerate() {
write!(f, "\n")?;
for (x, x_col) in z_grid.axis_iter(Axis(1)).enumerate() {
write!(f, "({},1,{}) = {{\"\n", x + 1, z + 1)?;
for &elem in x_col.iter() {
write!(f, "{}\n", map.format_key(elem))?;
}
write!(f, "\"}}\n")?;
}
}
Ok(())
}
// ----------------------------------------------------------------------------
@ -125,7 +217,7 @@ fn parse_map(map: &mut Map, f: File) -> io::Result<()> {
if ch == '"' {
curr_datum.push(ch);
in_quote_block = true;
} else if ch == '=' {
} else if ch == '=' && curr_var.is_empty() {
curr_var = take(&mut curr_datum);
let length = curr_var.trim_right().len();
curr_var.truncate(length);
@ -134,7 +226,9 @@ fn parse_map(map: &mut Map, f: File) -> io::Result<()> {
curr_prefab.vars.insert(take(&mut curr_var), take(&mut curr_datum));
skip_whitespace = true;
} else if ch == '}' {
curr_prefab.vars.insert(take(&mut curr_var), take(&mut curr_datum));
if !curr_var.is_empty() {
curr_prefab.vars.insert(take(&mut curr_var), take(&mut curr_datum));
}
in_varedit_block = false;
} else {
curr_datum.push(ch);

View file

@ -6,6 +6,7 @@ extern crate petgraph;
extern crate png;
extern crate inflate;
extern crate linked_hash_map;
#[macro_use] extern crate ndarray;
extern crate rand;

View file

@ -7,7 +7,7 @@ use petgraph::graph::{Graph, NodeIndex};
use xml::EventReader;
use xml::reader::XmlEvent;
pub type Vars = BTreeMap<String, String>;
pub type Vars = ::linked_hash_map::LinkedHashMap<String, String>;
#[derive(Debug)]
pub struct ObjectTree {
@ -54,7 +54,7 @@ impl ObjectTree {
let mut tree = ObjectTree {
graph: Graph::new(),
types: BTreeMap::new(),
blank_vars: BTreeMap::new(),
blank_vars: Default::default(),
};
let root = tree.graph.add_node(Type {
name: String::new(),