Partially working deleteobjects
This commit is contained in:
parent
2fd016bc22
commit
48502d81c9
12
Manual.md
12
Manual.md
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>>,
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user