Created
August 19, 2020 14:12
-
-
Save PJB3005/7fe68f7e96642a0a9363c52006f07102 to your computer and use it in GitHub Desktop.
DM Recipe export to JSON
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "dm-recipe-export" | |
version = "0.1.0" | |
authors = ["Pieter-Jan Briers <[email protected]>"] | |
edition = "2018" | |
[dependencies] | |
dreammaker = { path = "/home/pj/Projects/SpacemanDMM/src/dreammaker/" } | |
serde_json = "1.0.52" | |
serde = "1.0.107" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use dreammaker::ast::{Expression, Spanned, Term, FormatTypePath}; | |
use dreammaker::objtree::{ObjectTree, TypeRef, VarValue}; | |
use dreammaker::{constants::{Constant, Pop}, Context}; | |
use std::collections::HashMap; | |
use std::fs::File; | |
use std::path::PathBuf; | |
use std::ops::Deref; | |
use serde::{Serialize, Deserialize}; | |
#[derive(Serialize, Deserialize)] | |
struct MainData { | |
recipes: HashMap<String, Recipe> | |
} | |
#[derive(Serialize, Deserialize)] | |
struct Recipe { | |
name: String, | |
result: String, | |
reagents: Option<Vec<ReagentData>>, | |
items: Option<Vec<String>> | |
} | |
#[derive(Serialize, Deserialize)] | |
struct ReagentData { | |
allowed: Vec<String>, | |
amount: i32, | |
} | |
fn main() { | |
let context = Context::default(); | |
let path = PathBuf::from("/home/pj/Projects/vgstation13/vgstation13.dme"); | |
let tree = context.parse_environment(&path).unwrap(); | |
let recipes = discover_recipes(&tree); | |
let json = gen_data(&recipes); | |
let file = File::create("dump.json").unwrap(); | |
serde_json::to_writer_pretty(file, &json).unwrap(); | |
} | |
fn discover_recipes(o: &ObjectTree) -> Vec<TypeRef> { | |
let mut types = Vec::new(); | |
push_children(o.expect("/datum/recipe"), &mut types); | |
types | |
} | |
fn push_children<'a>(t: TypeRef<'a>, v: &mut Vec<TypeRef<'a>>) { | |
for x in t.children() { | |
v.push(x); | |
push_children(x, v); | |
} | |
} | |
fn gen_data(types: &[TypeRef]) -> MainData { | |
MainData { | |
recipes: types.iter() | |
.filter_map(|t| { | |
println!("{}", t.path); | |
let value = gen_recipe_data(*t); | |
match value { | |
Some(v) => Some((t.path.clone(), v)), | |
None => None, | |
} | |
}) | |
.collect() | |
} | |
} | |
fn gen_recipe_data(t: TypeRef) -> Option<Recipe> { | |
let result_var = t.get_value("result").unwrap(); | |
let result = match &result_var.constant.as_ref().unwrap() { | |
Constant::Prefab(p) => format!("{}", p), | |
_ => return None, | |
}; | |
let reagents = parse_reagents(t.get_value("reagents").unwrap()); | |
let items = parse_items(t.get_value("items").unwrap()); | |
Some(Recipe {name: t.name.clone(), result, reagents, items }) | |
} | |
fn parse_reagents(v: &VarValue) -> Option<Vec<ReagentData>> { | |
let expr_list = match v.expression.as_ref() { | |
Some(Expression::Base { | |
term: Spanned { | |
elem: Term::List(el), | |
.. | |
}, | |
.. | |
}) => el, | |
_ => return None, | |
}; | |
let reagent_list = expr_list.iter() | |
.map(|e| match e { | |
Expression::AssignOp { lhs, rhs, .. } => { | |
let m = (lhs.deref(), rhs.deref()); | |
match m { | |
( | |
Expression::Base { | |
term: | |
Spanned { | |
elem: lhs, | |
.. | |
}, | |
.. | |
}, | |
Expression::Base { | |
term: | |
Spanned { | |
elem: Term::Int(reagent_amount), | |
.. | |
}, | |
.. | |
}, | |
) => { | |
(lhs, *reagent_amount) | |
} | |
_ => panic!("Unexpected format!"), | |
} | |
} | |
_ => panic!("Unexpected format!"), | |
}); | |
Some(reagent_list.map(|r| { | |
let term = r.0; | |
let amount = r.1; | |
let allowed = match term { | |
Term::String(s) => vec![s.clone()], | |
Term::List(expressions) => { | |
expressions.iter().map(|e| { | |
match e { | |
Expression::Base { term: Spanned {elem: Term::String(s), ..}, ..} => { | |
s.clone() | |
}, | |
_ => panic!("Unexpected format!") | |
} | |
}).collect() | |
} | |
_ => panic!("Unexpected format!") | |
}; | |
ReagentData { amount, allowed } | |
}).collect()) | |
} | |
fn parse_items(v: &VarValue) -> Option<Vec<String>> { | |
let expr_list = match v.expression.as_ref() { | |
Some(Expression::Base { | |
term: Spanned { | |
elem: Term::List(el), | |
.. | |
}, | |
.. | |
}) => el, | |
_ => return None, | |
}; | |
Some(expr_list.iter() | |
.map(|e| match e { | |
Expression::Base {term: Spanned { elem: Term::Prefab(p), ..}, ..} => { | |
format!("{}", FormatTypePath(&p.path)) | |
}, | |
_ => panic!("Unexpected format!") | |
}).collect()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment