88 lines
2.4 KiB
Rust
88 lines
2.4 KiB
Rust
use super::Command;
|
|
|
|
use crate::unwrap_or;
|
|
use crate::spatial::Vec3;
|
|
use crate::instance::{ArgType, InstBundle};
|
|
use crate::map_block::{MapBlock, NodeMetadataList};
|
|
use crate::utils::{query_keys, fmt_big_num};
|
|
|
|
|
|
fn set_meta_var(inst: &mut InstBundle) {
|
|
let key = inst.args.key.as_ref().unwrap().as_bytes().to_owned();
|
|
let value = inst.args.value.as_ref().unwrap().as_bytes().to_owned();
|
|
let node = inst.args.node.as_ref().map(|s| s.as_bytes().to_owned());
|
|
|
|
let keys = query_keys(&mut inst.db, &mut inst.status,
|
|
node.iter().collect(), inst.args.area, inst.args.invert, true);
|
|
|
|
inst.status.begin_editing();
|
|
let mut count: u64 = 0;
|
|
|
|
for block_key in keys {
|
|
inst.status.inc_done();
|
|
let data = inst.db.get_block(block_key).unwrap();
|
|
let mut block = unwrap_or!(MapBlock::deserialize(&data), continue);
|
|
|
|
let node_data = block.node_data.get_ref();
|
|
let node_id = node.as_deref().and_then(|n| block.nimap.get_id(n));
|
|
if node.is_some() && node_id.is_none() {
|
|
continue; // Block doesn't contain the required node.
|
|
}
|
|
|
|
let mut meta = unwrap_or!(
|
|
NodeMetadataList::deserialize(block.metadata.get_ref()), continue);
|
|
|
|
let block_corner = Vec3::from_block_key(block_key) * 16;
|
|
let mut modified = false;
|
|
|
|
for (&idx, data) in &mut meta.list {
|
|
let pos = Vec3::from_u16_key(idx);
|
|
let abs_pos = pos + block_corner;
|
|
|
|
if let Some(a) = inst.args.area {
|
|
if a.contains(abs_pos) == inst.args.invert {
|
|
continue;
|
|
}
|
|
}
|
|
if let Some(id) = node_id {
|
|
if node_data.nodes[idx as usize] != id {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if let Some(val) = data.vars.get_mut(&key) {
|
|
val.0 = value.clone();
|
|
modified = true;
|
|
count += 1;
|
|
}
|
|
}
|
|
|
|
if modified {
|
|
*block.metadata.get_mut() = meta.serialize(block.version);
|
|
inst.db.set_block(block_key, &block.serialize()).unwrap();
|
|
}
|
|
}
|
|
|
|
inst.status.end_editing();
|
|
inst.status.log_info(
|
|
format!("Set metadata variable of {} nodes.", fmt_big_num(count)));
|
|
}
|
|
|
|
|
|
pub fn get_command() -> Command {
|
|
Command {
|
|
func: set_meta_var,
|
|
verify_args: None,
|
|
args: vec![
|
|
(ArgType::Key, "Name of key to set in metadata"),
|
|
(ArgType::Value, "Value to set in metadata"),
|
|
(ArgType::Area(false), "Area in which to modify node metadata"),
|
|
(ArgType::Invert, "Modify node metadata outside the given area."),
|
|
(ArgType::Node(false),
|
|
"Node to modify metadata in. If not specified, all relevant \
|
|
metadata will be modified.")
|
|
],
|
|
help: "Set a variable in node metadata."
|
|
}
|
|
}
|