deleteobjects work

master
random-geek 2021-01-20 00:17:35 -08:00
parent 2afbc8216b
commit b236c6d7d8
5 changed files with 78 additions and 3 deletions

View File

@ -49,6 +49,7 @@ fn to_cmd_line_args<'a>(tup: &(ArgType, &'a str))
];
}
vec![match arg {
// TODO: Remove unused conditions here.
ArgType::InputMapPath =>
Arg::with_name("input_map")
.required(true)
@ -90,6 +91,16 @@ fn to_cmd_line_args<'a>(tup: &(ArgType, &'a str))
Arg::with_name("param2_val")
.required(true)
.help(help),
ArgType::Object(req) =>
Arg::with_name("object")
.long("obj")
.takes_value(true)
.required(req)
.help(help),
ArgType::Items =>
Arg::with_name("items")
.long("items")
.help(help)
}]
}
@ -146,6 +157,8 @@ fn parse_cmd_line_args() -> anyhow::Result<InstArgs> {
new_node: sub_matches.value_of("new_node").map(str::to_string),
param2_val: sub_matches.value_of("param2_val")
.map(|v| v.parse().unwrap()),
object: sub_matches.value_of("object").map(str::to_string),
items: sub_matches.is_present("items"),
})
}

View File

@ -1,9 +1,11 @@
use super::Command;
use crate::instance::{ArgType, InstBundle};
use crate::map_block::{MapBlock};
use crate::map_block::{MapBlock, LuaEntityData};
use crate::utils::{query_keys, fmt_big_num};
use memmem::{Searcher, TwoWaySearcher};
macro_rules! unwrap_or {
($res:expr, $alt:expr) => {
@ -16,11 +18,20 @@ macro_rules! unwrap_or {
fn delete_objects(inst: &mut InstBundle) {
const ITEM_ENT_NAME: &'static [u8] = b"__builtin:item";
let search_obj = if inst.args.items {
Some(String::from_utf8(ITEM_ENT_NAME.to_vec()).unwrap())
} else {
inst.args.object.clone()
};
let keys = query_keys(&mut inst.db, &mut inst.status,
None, inst.args.area, inst.args.invert, true);
search_obj.clone(), inst.args.area, inst.args.invert, true);
inst.status.begin_editing();
let item_searcher = search_obj.as_ref().filter(|_| inst.args.items)
.map(|s| TwoWaySearcher::new(format!("[itemstring]=\"{}\"", s)));
let mut count: u64 = 0;
for key in keys {
inst.status.inc_done();
@ -31,6 +42,7 @@ fn delete_objects(inst: &mut InstBundle) {
for i in (0..block.static_objects.list.len()).rev() {
let obj = &block.static_objects.list[i];
// Check area requirements
if let Some(area) = inst.args.area {
const DIV_FAC: i32 = 10_000;
let rounded_pos = obj.f_pos.map(
@ -40,6 +52,26 @@ fn delete_objects(inst: &mut InstBundle) {
}
}
// Check name requirements
let le_data = unwrap_or!(LuaEntityData::deserialize(&obj),
continue);
if inst.args.items {
if le_data.name != ITEM_ENT_NAME {
continue;
}
if let Some(searcher) = &item_searcher {
if searcher.search_in(&le_data.data).is_none() {
continue;
}
}
} else {
if let Some(sobj) = &search_obj {
if le_data.name != sobj.as_bytes() {
continue;
}
}
}
block.static_objects.list.remove(i);
modified = true;
count += 1;
@ -62,6 +94,10 @@ pub fn get_command() -> Command {
args: vec![
(ArgType::Area(false), "Area in which to delete objects"),
(ArgType::Invert, "Delete all objects outside the area"),
(ArgType::Object(false),
"Name of object (or item with --item) to search for."),
(ArgType::Items,
"Delete dropped items using object name as item name."),
],
help: "Delete certain objects (entities)."
}

View File

@ -18,6 +18,8 @@ pub enum ArgType {
Node(bool),
NewNode(bool),
Param2Val(bool),
Object(bool),
Items,
}
@ -32,6 +34,8 @@ pub struct InstArgs {
pub node: Option<String>,
pub new_node: Option<String>,
pub param2_val: Option<u8>,
pub object: Option<String>,
pub items: bool,
}

View File

@ -15,7 +15,7 @@ pub use map_block::{MapBlock, is_valid_generated};
pub use compression::ZlibContainer;
pub use node_data::NodeData;
pub use metadata::NodeMetadataList;
pub use static_object::{StaticObject, StaticObjectList};
pub use static_object::{StaticObject, StaticObjectList, LuaEntityData};
pub use node_timer::{NodeTimer, NodeTimerList};
pub use name_id_map::NameIdMap;

View File

@ -62,3 +62,25 @@ impl StaticObjectList {
}
}
}
pub struct LuaEntityData {
pub name: Vec<u8>,
pub data: Vec<u8>
}
impl LuaEntityData {
pub fn deserialize(src: &StaticObject) -> Result<Self, MapBlockError> {
if src.obj_type != 7 {
return Err(MapBlockError::Other);
}
let mut src_data = Cursor::new(src.data.as_slice());
if src_data.read_u8()? != 1 {
return Err(MapBlockError::Other);
}
let name = read_string16(&mut src_data)?;
let data = read_string32(&mut src_data)?;
Ok(Self {name, data})
}
}