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
|
### 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:
|
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.
|
all objects will be deleted.
|
||||||
- `--items`: Search for only item entities (dropped items). If this flag is
|
- `--items [item]`: Delete item entities (dropped items). If an optional item
|
||||||
set, `--obj` can optionally be used to specify an item name.
|
name is specified, only items with that name will be deleted.
|
||||||
- `--p1, --p2`: Area in which to delete objects. If not specified, objects will
|
- `--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.
|
- `--invert`: Delete objects *outside* the given area.
|
||||||
|
|
||||||
### fill
|
### 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
|
[map_unexplore][5] project. All due credit goes to the author(s) of that
|
||||||
project.
|
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.
|
partially inspiring MapEdit/MapEditr.
|
||||||
|
|
||||||
[4]: https://github.com/minetest/minetest
|
[4]: https://github.com/minetest/minetest
|
||||||
|
@ -100,6 +100,8 @@ fn to_cmd_line_args<'a>(tup: &(ArgType, &'a str))
|
|||||||
ArgType::Items =>
|
ArgType::Items =>
|
||||||
Arg::with_name("items")
|
Arg::with_name("items")
|
||||||
.long("items")
|
.long("items")
|
||||||
|
.min_values(0)
|
||||||
|
.max_values(1)
|
||||||
.help(help)
|
.help(help)
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@ -158,7 +160,8 @@ fn parse_cmd_line_args() -> anyhow::Result<InstArgs> {
|
|||||||
param2_val: sub_matches.value_of("param2_val")
|
param2_val: sub_matches.value_of("param2_val")
|
||||||
.map(|v| v.parse().unwrap()),
|
.map(|v| v.parse().unwrap()),
|
||||||
object: sub_matches.value_of("object").map(str::to_string),
|
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};
|
use memmem::{Searcher, TwoWaySearcher};
|
||||||
|
|
||||||
|
|
||||||
|
const ITEM_ENT_NAME: &[u8] = b"__builtin:item";
|
||||||
|
|
||||||
|
|
||||||
macro_rules! unwrap_or {
|
macro_rules! unwrap_or {
|
||||||
($res:expr, $alt:expr) => {
|
($res:expr, $alt:expr) => {
|
||||||
match $res {
|
match $res {
|
||||||
@ -22,40 +25,59 @@ macro_rules! unwrap_or {
|
|||||||
fn can_delete(
|
fn can_delete(
|
||||||
obj: &StaticObject,
|
obj: &StaticObject,
|
||||||
area: &Option<Area>,
|
area: &Option<Area>,
|
||||||
invert: bool
|
invert: bool,
|
||||||
|
obj_name: &Option<Vec<u8>>,
|
||||||
|
item_searcher: &Option<TwoWaySearcher>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Check area requirements
|
// Check area requirement
|
||||||
if let Some(a) = area {
|
if let Some(a) = area {
|
||||||
const DIV_FAC: i32 = 10_000;
|
const DIV_FAC: i32 = 10_000;
|
||||||
let rounded_pos = obj.f_pos.map(
|
let rounded_pos = obj.f_pos.map(
|
||||||
|v| (v - DIV_FAC / 2).div_euclid(DIV_FAC));
|
|v| (v - DIV_FAC / 2).div_euclid(DIV_FAC));
|
||||||
if a.contains(rounded_pos) == invert {
|
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) {
|
fn delete_objects(inst: &mut InstBundle) {
|
||||||
const ITEM_ENT_NAME: &[u8] = b"__builtin:item";
|
let search_obj = if inst.args.items.is_some() {
|
||||||
let search_obj = if inst.args.items {
|
|
||||||
Some(ITEM_ENT_NAME.to_owned())
|
Some(ITEM_ENT_NAME.to_owned())
|
||||||
} else {
|
} else {
|
||||||
inst.args.object.as_ref().map(|s| s.as_bytes().to_owned())
|
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,
|
let keys = query_keys(&mut inst.db, &mut inst.status,
|
||||||
search_obj.as_deref(), inst.args.area, inst.args.invert, true);
|
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();
|
inst.status.begin_editing();
|
||||||
let mut count: u64 = 0;
|
let mut count: u64 = 0;
|
||||||
for key in keys {
|
for key in keys {
|
||||||
@ -65,12 +87,12 @@ fn delete_objects(inst: &mut InstBundle) {
|
|||||||
|
|
||||||
let mut modified = false;
|
let mut modified = false;
|
||||||
for i in (0..block.static_objects.list.len()).rev() {
|
for i in (0..block.static_objects.list.len()).rev() {
|
||||||
let obj = &block.static_objects.list[i];
|
|
||||||
|
|
||||||
if can_delete(
|
if can_delete(
|
||||||
&block.static_objects.list[i],
|
&block.static_objects.list[i],
|
||||||
&inst.args.area,
|
&inst.args.area,
|
||||||
inst.args.invert
|
inst.args.invert,
|
||||||
|
&search_obj,
|
||||||
|
&item_searcher
|
||||||
) {
|
) {
|
||||||
block.static_objects.list.remove(i);
|
block.static_objects.list.remove(i);
|
||||||
modified = true;
|
modified = true;
|
||||||
|
@ -35,7 +35,7 @@ pub struct InstArgs {
|
|||||||
pub new_node: Option<String>,
|
pub new_node: Option<String>,
|
||||||
pub param2_val: Option<u8>,
|
pub param2_val: Option<u8>,
|
||||||
pub object: Option<String>,
|
pub object: Option<String>,
|
||||||
pub items: bool,
|
pub items: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user