Gen7ScriptsRs/gen_7_scripts/build.rs

184 lines
5.3 KiB
Rust

use std::io::Write;
fn main() {
let mut output_file = std::fs::File::create("src/registered_scripts.rs").unwrap();
write!(
output_file,
r"// Autogenerated file. Do not edit.
use alloc::boxed::Box;
use pkmn_lib_interface::app_interface::{{get_hash, StringKey}};
use pkmn_lib_interface::handling::{{Script, ScriptCategory}};
use pkmn_lib_interface::handling::item_script::ItemScript;
macro_rules! resolve_match {{
(
$mid:expr,
$(
$script:ty,
)*
) => (
match $mid {{
$(
const {{ get_hash(<$script>::get_const_name()) }} => {{
return Some(Box::new(<$script>::new()))
}}
)*
_ => {{}}
}}
)
}}
pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn Script>> {{
match category {{"
)
.unwrap();
write_category("moves", "Move", &mut output_file);
write_category("abilities", "Ability", &mut output_file);
write_category("status", "Status", &mut output_file);
write_category("pokemon", "Pokemon", &mut output_file);
write_category("battle", "Battle", &mut output_file);
write_category("weather", "Weather", &mut output_file);
write_category("side", "Side", &mut output_file);
write_category(
"item_battle_triggers",
"ItemBattleTrigger",
&mut output_file,
);
write!(
output_file,
r#"
}}
None
}}
"#
)
.unwrap();
write_item_scripts(&mut output_file);
}
fn write_category(path: &str, category: &str, output_file: &mut std::fs::File) {
write!(
output_file,
r"
ScriptCategory::{} => {{
resolve_match! {{
name.hash().unwrap(),
",
category
)
.unwrap();
write_scripts(path, output_file);
write!(
output_file,
r" }}
}},"
)
.unwrap();
}
fn write_scripts(path: &str, output_file: &mut std::fs::File) {
let move_files = std::fs::read_dir(format!("src/{}", path))
.unwrap()
.map(|f| f.unwrap().path())
.filter(|f| f.extension().unwrap() == "rs")
.map(|f| f.file_stem().unwrap().to_str().unwrap().to_string())
.collect::<Vec<_>>();
for file in move_files {
println!("cargo:rerun-if-changed=src/{}/{}.rs", path, file);
let parsed =
syn::parse_file(&std::fs::read_to_string(format!("src/{}/{}.rs", path, file)).unwrap())
.unwrap();
// Now we need to find every impl Script for X { ... } block inside parsed
let script_impls = parsed
.items
.iter()
.filter_map(|item| match item {
syn::Item::Impl(impl_block) => match impl_block.trait_ {
Some((_, ref path, _)) => {
if path.segments[0].ident == "Script" {
Some(impl_block)
} else {
None
}
}
None => None,
},
_ => None,
})
.collect::<Vec<_>>();
for script_impl in script_impls {
if let syn::Type::Path(p) = script_impl.self_ty.as_ref() {
let ident = p.path.segments[0].ident.to_string();
writeln!(
output_file,
" crate::{}::{}::{},",
path, file, ident
)
.unwrap();
}
}
}
}
fn write_item_scripts(output_file: &mut std::fs::File) {
writeln!(
output_file,
r"
pub fn get_item_script(name: &StringKey) -> Option<Box<dyn ItemScript>> {{
resolve_match! {{
name.hash().unwrap(),"
)
.unwrap();
let item_files = std::fs::read_dir("src/items")
.unwrap()
.map(|f| f.unwrap().path())
.filter(|f| f.extension().unwrap() == "rs")
.map(|f| f.file_stem().unwrap().to_str().unwrap().to_string())
.collect::<Vec<_>>();
for file in item_files {
println!("cargo:rerun-if-changed=src/items/{}.rs", file);
let parsed =
syn::parse_file(&std::fs::read_to_string(format!("src/items/{}.rs", file)).unwrap())
.unwrap();
// Now we need to find every impl ItemScript for X { ... } block inside parsed
let script_impls = parsed
.items
.iter()
.filter_map(|item| match item {
syn::Item::Impl(impl_block) => match impl_block.trait_ {
Some((_, ref path, _)) => {
if path.segments[0].ident == "ItemScript" {
Some(impl_block)
} else {
None
}
}
None => None,
},
_ => None,
})
.collect::<Vec<_>>();
for script_impl in script_impls {
if let syn::Type::Path(p) = script_impl.self_ty.as_ref() {
let ident = p.path.segments[0].ident.to_string();
writeln!(output_file, " crate::items::{}::{},", file, ident).unwrap();
}
}
}
writeln!(
output_file,
r" }}
None
}}"
)
.unwrap();
}