Partially working deleteobjects

master
random-geek 2021-01-22 00:03:11 -08:00
parent 2fd016bc22
commit 48502d81c9
5 changed files with 51 additions and 26 deletions

View File

@ -76,18 +76,18 @@ terrain glitches.
### deleteobjects
Usage: `deleteobjects [--obj <obj>] [--items] [--p1 x y z] [--p2 x y z] [--invert]`
Usage: `deleteobjects [--obj <object>] [--items [item]] [--p1 x y z] [--p2 x y z] [--invert]`
Delete objects (entities) of a certain name and/or within a certain area.
Delete objects/entities, including item entities (dropped items).
Arguments:
- `--obj`: Name of object to search for, e.g. "boats:boat". If not specified,
- `--obj`: Name of object to delete, e.g. "boats:boat". If not specified,
all objects will be deleted.
- `--items`: Search for only item entities (dropped items). If this flag is
set, `--obj` can optionally be used to specify an item name.
- `--items [item]`: Delete item entities (dropped items). If an optional item
name is specified, only items with that name will be deleted.
- `--p1, --p2`: Area in which to delete objects. If not specified, objects will
be deleted across the entire map.
be deleted everywhere.
- `--invert`: Delete objects *outside* the given area.
### fill

View File

@ -53,7 +53,7 @@ Some parts of the original MapEdit code were adapted from AndrejIT's
[map_unexplore][5] project. All due credit goes to the author(s) of that
project.
Thank you to ExeterDad and the moderators of the late Hometown server, for
Thank you also to ExeterDad and the moderators of the late Hometown server, for
partially inspiring MapEdit/MapEditr.
[4]: https://github.com/minetest/minetest

View File

@ -100,6 +100,8 @@ fn to_cmd_line_args<'a>(tup: &(ArgType, &'a str))
ArgType::Items =>
Arg::with_name("items")
.long("items")
.min_values(0)
.max_values(1)
.help(help)
}]
}
@ -158,7 +160,8 @@ fn parse_cmd_line_args() -> anyhow::Result<InstArgs> {
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"),
items: sub_matches.values_of("items")
.map(|v| v.map(str::to_string).collect()),
})
}

View File

@ -8,6 +8,9 @@ use crate::utils::{query_keys, fmt_big_num};
use memmem::{Searcher, TwoWaySearcher};
const ITEM_ENT_NAME: &[u8] = b"__builtin:item";
macro_rules! unwrap_or {
($res:expr, $alt:expr) => {
match $res {
@ -22,40 +25,59 @@ macro_rules! unwrap_or {
fn can_delete(
obj: &StaticObject,
area: &Option<Area>,
invert: bool
invert: bool,
obj_name: &Option<Vec<u8>>,
item_searcher: &Option<TwoWaySearcher>
) -> bool {
// Check area requirements
// Check area requirement
if let Some(a) = area {
const DIV_FAC: i32 = 10_000;
let rounded_pos = obj.f_pos.map(
|v| (v - DIV_FAC / 2).div_euclid(DIV_FAC));
if a.contains(rounded_pos) == invert {
return false;
return false; // Object not included in area.
}
}
true
// Check name requirement
if let Some(n) = obj_name {
if let Ok(le_data) = LuaEntityData::deserialize(obj) {
if &le_data.name != n {
return false; // Object name does not match.
}
if let Some(is) = item_searcher {
if is.search_in(&le_data.data).is_none() {
return false; // Item entity name does not match.
}
}
} else {
return false; // Unsupported object type, don't delete it.
}
}
true // Delete if all tests pass.
}
fn delete_objects(inst: &mut InstBundle) {
const ITEM_ENT_NAME: &[u8] = b"__builtin:item";
let search_obj = if inst.args.items {
let search_obj = if inst.args.items.is_some() {
Some(ITEM_ENT_NAME.to_owned())
} else {
inst.args.object.as_ref().map(|s| s.as_bytes().to_owned())
};
// search_item will be Some if (1) item search is enabled and (2) an item
// is specified.
let search_item = inst.args.items.as_ref()
.and_then(|items| items.get(0))
.map(|s| s.as_bytes().to_owned());
let item_searcher = search_item.as_ref()
.map(|s| TwoWaySearcher::new(s));
let keys = query_keys(&mut inst.db, &mut inst.status,
search_obj.as_deref(), inst.args.area, inst.args.invert, true);
let search_item = search_obj.as_ref().filter(|_| inst.args.items).map(|s|
format!(
"[\"itemstring\"] = \"{}\"",
String::from_utf8(s.to_owned()).unwrap()
).into_bytes()
);
let item_searcher = search_item.as_ref().map(|s| TwoWaySearcher::new(s));
inst.status.begin_editing();
let mut count: u64 = 0;
for key in keys {
@ -65,12 +87,12 @@ fn delete_objects(inst: &mut InstBundle) {
let mut modified = false;
for i in (0..block.static_objects.list.len()).rev() {
let obj = &block.static_objects.list[i];
if can_delete(
&block.static_objects.list[i],
&inst.args.area,
inst.args.invert
inst.args.invert,
&search_obj,
&item_searcher
) {
block.static_objects.list.remove(i);
modified = true;

View File

@ -35,7 +35,7 @@ pub struct InstArgs {
pub new_node: Option<String>,
pub param2_val: Option<u8>,
pub object: Option<String>,
pub items: bool,
pub items: Option<Vec<String>>,
}