84 lines
2.0 KiB
Rust
84 lines
2.0 KiB
Rust
use super::Command;
|
|
|
|
use crate::unwrap_or;
|
|
use crate::spatial::{Vec3, Area};
|
|
use crate::instance::{ArgType, InstBundle};
|
|
use crate::map_block::MapBlock;
|
|
use crate::block_utils::clean_name_id_map;
|
|
use crate::utils::{query_keys, to_bytes, fmt_big_num};
|
|
|
|
|
|
fn fill_area(block: &mut MapBlock, area: Area, id: u16) {
|
|
let nd = block.node_data.get_mut();
|
|
for z in area.min.z ..= area.max.z {
|
|
let z_start = z * 256;
|
|
for y in area.min.y ..= area.max.y {
|
|
let zy_start = z_start + y * 16;
|
|
for x in area.min.x ..= area.max.x {
|
|
nd.nodes[(zy_start + x) as usize] = id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
fn fill(inst: &mut InstBundle) {
|
|
let area = inst.args.area.unwrap();
|
|
let node = to_bytes(inst.args.new_node.as_ref().unwrap());
|
|
|
|
let keys = query_keys(&mut inst.db, &mut inst.status,
|
|
&[], Some(area), false, true);
|
|
|
|
inst.status.begin_editing();
|
|
|
|
let mut count: u64 = 0;
|
|
for key in keys {
|
|
inst.status.inc_done();
|
|
|
|
let pos = Vec3::from_block_key(key);
|
|
let data = inst.db.get_block(key).unwrap();
|
|
let mut block = unwrap_or!(MapBlock::deserialize(&data), {
|
|
inst.status.inc_failed();
|
|
continue;
|
|
});
|
|
|
|
if area.contains_block(pos) {
|
|
let nd = block.node_data.get_mut();
|
|
for x in &mut nd.nodes {
|
|
*x = 0;
|
|
}
|
|
block.nimap.0.clear();
|
|
block.nimap.0.insert(0, node.to_vec());
|
|
count += nd.nodes.len() as u64;
|
|
} else {
|
|
let slice = area.rel_block_overlap(pos).unwrap();
|
|
let fill_id = block.nimap.get_id(&node).unwrap_or_else(|| {
|
|
let next = block.nimap.get_max_id().unwrap() + 1;
|
|
block.nimap.0.insert(next, node.to_vec());
|
|
next
|
|
});
|
|
fill_area(&mut block, slice, fill_id);
|
|
clean_name_id_map(&mut block);
|
|
count += slice.volume();
|
|
}
|
|
|
|
inst.db.set_block(key, &block.serialize()).unwrap();
|
|
}
|
|
|
|
inst.status.end_editing();
|
|
inst.status.log_info(format!("{} nodes filled.", fmt_big_num(count)));
|
|
}
|
|
|
|
|
|
pub fn get_command() -> Command {
|
|
Command {
|
|
func: fill,
|
|
verify_args: None,
|
|
args: vec![
|
|
(ArgType::Area(true), "Area to fill"),
|
|
(ArgType::NewNode, "Name of node to fill area with")
|
|
],
|
|
help: "Fill the entire area with one node."
|
|
}
|
|
}
|