mostly working deletetimers
This commit is contained in:
parent
48502d81c9
commit
2a7b9705d0
@ -1,5 +1,6 @@
|
|||||||
use super::Command;
|
use super::Command;
|
||||||
|
|
||||||
|
use crate::unwrap_or;
|
||||||
use crate::spatial::Area;
|
use crate::spatial::Area;
|
||||||
use crate::instance::{ArgType, InstBundle};
|
use crate::instance::{ArgType, InstBundle};
|
||||||
use crate::map_block::{MapBlock, StaticObject, LuaEntityData};
|
use crate::map_block::{MapBlock, StaticObject, LuaEntityData};
|
||||||
@ -7,20 +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";
|
const ITEM_ENT_NAME: &[u8] = b"__builtin:item";
|
||||||
|
|
||||||
|
|
||||||
macro_rules! unwrap_or {
|
|
||||||
($res:expr, $alt:expr) => {
|
|
||||||
match $res {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(_) => $alt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn can_delete(
|
fn can_delete(
|
||||||
obj: &StaticObject,
|
obj: &StaticObject,
|
||||||
@ -118,9 +108,11 @@ pub fn get_command() -> Command {
|
|||||||
(ArgType::Area(false), "Area in which to delete objects"),
|
(ArgType::Area(false), "Area in which to delete objects"),
|
||||||
(ArgType::Invert, "Delete all objects outside the area"),
|
(ArgType::Invert, "Delete all objects outside the area"),
|
||||||
(ArgType::Object(false),
|
(ArgType::Object(false),
|
||||||
"Name of object (or item with --item) to search for."),
|
"Name of object to delete. If not specified, all objects will \
|
||||||
|
be deleted"),
|
||||||
(ArgType::Items,
|
(ArgType::Items,
|
||||||
"Delete dropped items using object name as item name."),
|
"Delete item entities. Optionally specify an item name to \
|
||||||
|
delete."),
|
||||||
],
|
],
|
||||||
help: "Delete certain objects (entities)."
|
help: "Delete certain objects (entities)."
|
||||||
}
|
}
|
||||||
|
79
src/commands/delete_timers.rs
Normal file
79
src/commands/delete_timers.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
use super::Command;
|
||||||
|
|
||||||
|
use crate::unwrap_or;
|
||||||
|
use crate::spatial::Vec3;
|
||||||
|
use crate::instance::{ArgType, InstBundle};
|
||||||
|
use crate::map_block::MapBlock;
|
||||||
|
use crate::utils::{query_keys, fmt_big_num};
|
||||||
|
|
||||||
|
|
||||||
|
fn delete_timers(inst: &mut InstBundle) {
|
||||||
|
let node = inst.args.node.as_ref().map(|s| s.as_bytes().to_owned());
|
||||||
|
|
||||||
|
let keys = query_keys(&mut inst.db, &mut inst.status,
|
||||||
|
node.as_deref(), inst.args.area, inst.args.invert, true);
|
||||||
|
|
||||||
|
inst.status.begin_editing();
|
||||||
|
let mut count: u64 = 0;
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
inst.status.inc_done();
|
||||||
|
let data = inst.db.get_block(key).unwrap();
|
||||||
|
let mut block = unwrap_or!(MapBlock::deserialize(&data), continue);
|
||||||
|
|
||||||
|
let node_id = node.as_deref().and_then(|n| block.nimap.get_id(n));
|
||||||
|
if node.is_some() && node_id.is_none() {
|
||||||
|
continue; // Block doesn't contain the required node.
|
||||||
|
}
|
||||||
|
let node_data = block.node_data.get_ref();
|
||||||
|
|
||||||
|
let block_corner = Vec3::from_block_key(key) * 16;
|
||||||
|
let mut modified = false;
|
||||||
|
|
||||||
|
for i in (0..block.node_timers.len()).rev() {
|
||||||
|
let pos_idx = block.node_timers[i].pos;
|
||||||
|
let pos = Vec3::from_u16_key(pos_idx);
|
||||||
|
let abs_pos = pos + block_corner;
|
||||||
|
|
||||||
|
if let Some(a) = inst.args.area {
|
||||||
|
if a.contains(abs_pos) == inst.args.invert {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(id) = node_id {
|
||||||
|
if node_data.nodes[pos_idx as usize] != id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block.node_timers.remove(i);
|
||||||
|
count += 1;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if modified {
|
||||||
|
inst.db.set_block(key, &block.serialize()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inst.status.end_editing();
|
||||||
|
inst.status.log_info(
|
||||||
|
format!("Deleted {} node timers.", fmt_big_num(count)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_command() -> Command {
|
||||||
|
Command {
|
||||||
|
func: delete_timers,
|
||||||
|
verify_args: None,
|
||||||
|
args: vec![
|
||||||
|
(ArgType::Area(false), "Area in which to delete timers"),
|
||||||
|
(ArgType::Invert, "Delete all timers outside the given area."),
|
||||||
|
(ArgType::Node(false),
|
||||||
|
"Node to delete timers from. If not specified, all node \
|
||||||
|
timers will be deleted.")
|
||||||
|
],
|
||||||
|
help: "Delete node timers."
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ use crate::instance::{ArgType, InstArgs, InstBundle};
|
|||||||
mod clone;
|
mod clone;
|
||||||
mod delete_blocks;
|
mod delete_blocks;
|
||||||
mod delete_objects;
|
mod delete_objects;
|
||||||
|
mod delete_timers;
|
||||||
mod fill;
|
mod fill;
|
||||||
mod overlay;
|
mod overlay;
|
||||||
mod replace_nodes;
|
mod replace_nodes;
|
||||||
@ -31,6 +32,7 @@ pub fn get_commands() -> BTreeMap<&'static str, Command> {
|
|||||||
new_cmd!("clone", clone);
|
new_cmd!("clone", clone);
|
||||||
new_cmd!("deleteblocks", delete_blocks);
|
new_cmd!("deleteblocks", delete_blocks);
|
||||||
new_cmd!("deleteobjects", delete_objects);
|
new_cmd!("deleteobjects", delete_objects);
|
||||||
|
new_cmd!("deletetimers", delete_timers);
|
||||||
new_cmd!("fill", fill);
|
new_cmd!("fill", fill);
|
||||||
new_cmd!("replacenodes", replace_nodes);
|
new_cmd!("replacenodes", replace_nodes);
|
||||||
new_cmd!("overlay", overlay);
|
new_cmd!("overlay", overlay);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use super::node_timer::{serialize_timers, deserialize_timers};
|
||||||
|
|
||||||
const MIN_BLOCK_VER: u8 = 25;
|
const MIN_BLOCK_VER: u8 = 25;
|
||||||
const MAX_BLOCK_VER: u8 = 28;
|
const MAX_BLOCK_VER: u8 = 28;
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ pub struct MapBlock {
|
|||||||
pub static_objects: StaticObjectList,
|
pub static_objects: StaticObjectList,
|
||||||
pub timestamp: u32,
|
pub timestamp: u32,
|
||||||
pub nimap: NameIdMap,
|
pub nimap: NameIdMap,
|
||||||
pub node_timers: NodeTimerList
|
pub node_timers: Vec<NodeTimer>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapBlock {
|
impl MapBlock {
|
||||||
@ -64,7 +66,7 @@ impl MapBlock {
|
|||||||
// Name-ID mappings
|
// Name-ID mappings
|
||||||
let nimap = NameIdMap::deserialize(&mut data)?;
|
let nimap = NameIdMap::deserialize(&mut data)?;
|
||||||
// Node timers
|
// Node timers
|
||||||
let node_timers = NodeTimerList::deserialize(&mut data)?;
|
let node_timers = deserialize_timers(&mut data)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
version,
|
version,
|
||||||
@ -113,7 +115,7 @@ impl MapBlock {
|
|||||||
// Name-ID mappings
|
// Name-ID mappings
|
||||||
self.nimap.serialize(&mut data);
|
self.nimap.serialize(&mut data);
|
||||||
// Node timers
|
// Node timers
|
||||||
self.node_timers.serialize(&mut data);
|
serialize_timers(&self.node_timers, &mut data);
|
||||||
|
|
||||||
buf = data.into_inner();
|
buf = data.into_inner();
|
||||||
buf.shrink_to_fit();
|
buf.shrink_to_fit();
|
||||||
|
@ -3,47 +3,44 @@ use super::*;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NodeTimer {
|
pub struct NodeTimer {
|
||||||
pos: u16,
|
pub pos: u16,
|
||||||
timeout: u32,
|
pub timeout: u32,
|
||||||
elapsed: u32
|
pub elapsed: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub type NodeTimerList = Vec<NodeTimer>;
|
||||||
pub struct NodeTimerList {
|
|
||||||
timers: Vec<NodeTimer>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeTimerList {
|
|
||||||
pub fn deserialize(data: &mut Cursor<&[u8]>)
|
|
||||||
-> Result<Self, MapBlockError>
|
|
||||||
{
|
|
||||||
let data_len = data.read_u8()?;
|
|
||||||
if data_len != 10 {
|
|
||||||
return Err(MapBlockError::Other);
|
|
||||||
}
|
|
||||||
|
|
||||||
let count = data.read_u16::<BigEndian>()?;
|
pub fn deserialize_timers(src: &mut Cursor<&[u8]>)
|
||||||
let mut timers = Vec::with_capacity(count as usize);
|
-> Result<NodeTimerList, MapBlockError>
|
||||||
|
{
|
||||||
for _ in 0 .. count {
|
let data_len = src.read_u8()?;
|
||||||
let pos = data.read_u16::<BigEndian>()?;
|
if data_len != 10 {
|
||||||
let timeout = data.read_u32::<BigEndian>()?;
|
return Err(MapBlockError::Other);
|
||||||
let elapsed = data.read_u32::<BigEndian>()?;
|
|
||||||
timers.push(NodeTimer {pos, timeout, elapsed});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(NodeTimerList {timers})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize(&self, data: &mut Cursor<Vec<u8>>) {
|
let count = src.read_u16::<BigEndian>()?;
|
||||||
data.write_u8(10).unwrap();
|
let mut timers = Vec::with_capacity(count as usize);
|
||||||
data.write_u16::<BigEndian>(self.timers.len() as u16).unwrap();
|
|
||||||
|
|
||||||
for t in &self.timers {
|
for _ in 0 .. count {
|
||||||
data.write_u16::<BigEndian>(t.pos).unwrap();
|
let pos = src.read_u16::<BigEndian>()?;
|
||||||
data.write_u32::<BigEndian>(t.timeout).unwrap();
|
let timeout = src.read_u32::<BigEndian>()?;
|
||||||
data.write_u32::<BigEndian>(t.elapsed).unwrap();
|
let elapsed = src.read_u32::<BigEndian>()?;
|
||||||
}
|
timers.push(NodeTimer {pos, timeout, elapsed});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(timers)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn serialize_timers(timers: &NodeTimerList, dst: &mut Cursor<Vec<u8>>) {
|
||||||
|
dst.write_u8(10).unwrap();
|
||||||
|
dst.write_u16::<BigEndian>(timers.len() as u16).unwrap();
|
||||||
|
|
||||||
|
for t in timers {
|
||||||
|
dst.write_u16::<BigEndian>(t.pos).unwrap();
|
||||||
|
dst.write_u32::<BigEndian>(t.timeout).unwrap();
|
||||||
|
dst.write_u32::<BigEndian>(t.elapsed).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
src/utils.rs
11
src/utils.rs
@ -67,6 +67,17 @@ pub fn query_keys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! unwrap_or {
|
||||||
|
($res:expr, $alt:expr) => {
|
||||||
|
match $res {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(_) => $alt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn fmt_duration(dur: Duration) -> String {
|
pub fn fmt_duration(dur: Duration) -> String {
|
||||||
let s = dur.as_secs();
|
let s = dur.as_secs();
|
||||||
if s < 3600 {
|
if s < 3600 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user