From 2a7b9705d05416da75079d315782fa943939b328 Mon Sep 17 00:00:00 2001 From: random-geek <35757396+random-geek@users.noreply.github.com> Date: Fri, 22 Jan 2021 14:44:58 -0800 Subject: [PATCH] mostly working deletetimers --- src/commands/delete_objects.rs | 18 +++----- src/commands/delete_timers.rs | 79 ++++++++++++++++++++++++++++++++++ src/commands/mod.rs | 2 + src/map_block/map_block.rs | 8 ++-- src/map_block/node_timer.rs | 65 +++++++++++++--------------- src/utils.rs | 11 +++++ 6 files changed, 133 insertions(+), 50 deletions(-) create mode 100644 src/commands/delete_timers.rs diff --git a/src/commands/delete_objects.rs b/src/commands/delete_objects.rs index a215648..b1d8ffe 100644 --- a/src/commands/delete_objects.rs +++ b/src/commands/delete_objects.rs @@ -1,5 +1,6 @@ use super::Command; +use crate::unwrap_or; use crate::spatial::Area; use crate::instance::{ArgType, InstBundle}; use crate::map_block::{MapBlock, StaticObject, LuaEntityData}; @@ -7,20 +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 { - Ok(val) => val, - Err(_) => $alt - } - } -} - - #[inline] fn can_delete( obj: &StaticObject, @@ -118,9 +108,11 @@ pub fn get_command() -> Command { (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."), + "Name of object to delete. If not specified, all objects will \ + be deleted"), (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)." } diff --git a/src/commands/delete_timers.rs b/src/commands/delete_timers.rs new file mode 100644 index 0000000..df6232b --- /dev/null +++ b/src/commands/delete_timers.rs @@ -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." + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 424ab3a..c637860 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -5,6 +5,7 @@ use crate::instance::{ArgType, InstArgs, InstBundle}; mod clone; mod delete_blocks; mod delete_objects; +mod delete_timers; mod fill; mod overlay; mod replace_nodes; @@ -31,6 +32,7 @@ pub fn get_commands() -> BTreeMap<&'static str, Command> { new_cmd!("clone", clone); new_cmd!("deleteblocks", delete_blocks); new_cmd!("deleteobjects", delete_objects); + new_cmd!("deletetimers", delete_timers); new_cmd!("fill", fill); new_cmd!("replacenodes", replace_nodes); new_cmd!("overlay", overlay); diff --git a/src/map_block/map_block.rs b/src/map_block/map_block.rs index a21d2fb..93694aa 100644 --- a/src/map_block/map_block.rs +++ b/src/map_block/map_block.rs @@ -1,5 +1,7 @@ use super::*; +use super::node_timer::{serialize_timers, deserialize_timers}; + const MIN_BLOCK_VER: u8 = 25; const MAX_BLOCK_VER: u8 = 28; @@ -25,7 +27,7 @@ pub struct MapBlock { pub static_objects: StaticObjectList, pub timestamp: u32, pub nimap: NameIdMap, - pub node_timers: NodeTimerList + pub node_timers: Vec } impl MapBlock { @@ -64,7 +66,7 @@ impl MapBlock { // Name-ID mappings let nimap = NameIdMap::deserialize(&mut data)?; // Node timers - let node_timers = NodeTimerList::deserialize(&mut data)?; + let node_timers = deserialize_timers(&mut data)?; Ok(Self { version, @@ -113,7 +115,7 @@ impl MapBlock { // Name-ID mappings self.nimap.serialize(&mut data); // Node timers - self.node_timers.serialize(&mut data); + serialize_timers(&self.node_timers, &mut data); buf = data.into_inner(); buf.shrink_to_fit(); diff --git a/src/map_block/node_timer.rs b/src/map_block/node_timer.rs index 9d665be..e57bef9 100644 --- a/src/map_block/node_timer.rs +++ b/src/map_block/node_timer.rs @@ -3,47 +3,44 @@ use super::*; #[derive(Debug)] pub struct NodeTimer { - pos: u16, - timeout: u32, - elapsed: u32 + pub pos: u16, + pub timeout: u32, + pub elapsed: u32 } -#[derive(Debug)] -pub struct NodeTimerList { - timers: Vec -} +pub type NodeTimerList = Vec; -impl NodeTimerList { - pub fn deserialize(data: &mut Cursor<&[u8]>) - -> Result - { - let data_len = data.read_u8()?; - if data_len != 10 { - return Err(MapBlockError::Other); - } - let count = data.read_u16::()?; - let mut timers = Vec::with_capacity(count as usize); - - for _ in 0 .. count { - let pos = data.read_u16::()?; - let timeout = data.read_u32::()?; - let elapsed = data.read_u32::()?; - timers.push(NodeTimer {pos, timeout, elapsed}); - } - - Ok(NodeTimerList {timers}) +pub fn deserialize_timers(src: &mut Cursor<&[u8]>) + -> Result +{ + let data_len = src.read_u8()?; + if data_len != 10 { + return Err(MapBlockError::Other); } - pub fn serialize(&self, data: &mut Cursor>) { - data.write_u8(10).unwrap(); - data.write_u16::(self.timers.len() as u16).unwrap(); + let count = src.read_u16::()?; + let mut timers = Vec::with_capacity(count as usize); - for t in &self.timers { - data.write_u16::(t.pos).unwrap(); - data.write_u32::(t.timeout).unwrap(); - data.write_u32::(t.elapsed).unwrap(); - } + for _ in 0 .. count { + let pos = src.read_u16::()?; + let timeout = src.read_u32::()?; + let elapsed = src.read_u32::()?; + timers.push(NodeTimer {pos, timeout, elapsed}); + } + + Ok(timers) +} + + +pub fn serialize_timers(timers: &NodeTimerList, dst: &mut Cursor>) { + dst.write_u8(10).unwrap(); + dst.write_u16::(timers.len() as u16).unwrap(); + + for t in timers { + dst.write_u16::(t.pos).unwrap(); + dst.write_u32::(t.timeout).unwrap(); + dst.write_u32::(t.elapsed).unwrap(); } } diff --git a/src/utils.rs b/src/utils.rs index ff3f56f..94e9f58 100644 --- a/src/utils.rs +++ b/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 { let s = dur.as_secs(); if s < 3600 {