diff --git a/CHANGELOG.md b/CHANGELOG.md index cced82b..b02c9b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ It's about time I started a changelog! This will serve from now on as the main c ## v1.12 (unreleased) - Add `//srect` (_select rectangle_) - thanks, @VorTechnix! + - Add `//spush`, `//spop`, and `//sstack` + ## v1.11: The big data update (25th January 2021) - Add `//scale` (currently **experimental**) diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index 49acea4..9ed6be0 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -45,3 +45,4 @@ dofile(worldeditadditions.modpath.."/lib/forest.lua") dofile(worldeditadditions.modpath.."/lib/ellipsoidapply.lua") dofile(worldeditadditions.modpath.."/lib/subdivide.lua") +dofile(worldeditadditions.modpath.."/lib/selection/stack.lua") diff --git a/worldeditadditions/lib/selection/stack.lua b/worldeditadditions/lib/selection/stack.lua new file mode 100644 index 0000000..7ef7a0d --- /dev/null +++ b/worldeditadditions/lib/selection/stack.lua @@ -0,0 +1,47 @@ +--- Holds the per-user selection stacks. +worldeditadditions.sstack = {} + +local sstack_max = 100 + +--- Calculates the height of the selection stack for the defined user. +-- If the defined user doesn't yet have a stack, a value of 0 is returned. +-- @param user string The name of the user to count the size of the selection stack for. +-- @return number The number of items on the stack for the given user. +function worldeditadditions.scount(name) + if not worldeditadditions.sstack[name] then + return 0 + end + return #worldeditadditions.sstack[name] +end + +--- Inserts a selection region onto the stack for the user with the given name. +-- Stacks are per-user. +-- @param name string The name of the user to insert onto. +-- @param pos1 Vector Position 1 +-- @param pos2 Vector Position 2 +function worldeditadditions.spush(name, pos1, pos2) + if not worldeditadditions.sstack[name] then + worldeditadditions.sstack[name] = {} + end + -- Checck the stack height + if #worldeditadditions.sstack[name] > sstack_max then + return false, "Error: Selection stack height of "..sstack_max.." would be exceeded by pushing a new selection onto the stack now." + end + + table.insert(worldeditadditions.sstack[name], { pos1, pos2 }) + + return true +end + +--- Pops a selection region off the stack for the given user. +-- Stacks are per-user. +-- @param name string The name of the user to remove a selection region off the stack for. +-- @return bool,Vector|string, Vector A bool true/false indicating success, followed by either a error message as a string if false or a pair of Vectors for the pos1 and pos2 from the item popped from the stack respectively. +function worldeditadditions.spop(name) + if not worldeditadditions.sstack[name] or #worldeditadditions.sstack[name] == 0 then + return false, "Error: The stack for user "..name.." is empty, so can't remove anything from it." + end + + local item = table.remove(worldeditadditions.sstack[name]) + return true, item[1], item[2] +end diff --git a/worldeditadditions/utils/vector.lua b/worldeditadditions/utils/vector.lua index 75f2b75..3df6611 100644 --- a/worldeditadditions/utils/vector.lua +++ b/worldeditadditions/utils/vector.lua @@ -1,6 +1,7 @@ worldeditadditions.vector = {} function worldeditadditions.vector.tostring(v) + if not v then return "(nil)" end return "(" .. v.x ..", " .. v.y ..", " .. v.z ..")" end diff --git a/worldeditadditions_commands/commands/selectors/spop.lua b/worldeditadditions_commands/commands/selectors/spop.lua new file mode 100644 index 0000000..0e3ea9c --- /dev/null +++ b/worldeditadditions_commands/commands/selectors/spop.lua @@ -0,0 +1,33 @@ +-- ███████ ██████ ██████ ██████ +-- ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██████ ██ ██ ██████ +-- ██ ██ ██ ██ ██ +-- ███████ ██ ██████ ██ +worldedit.register_command("spop", { + params = "", + description = "Pops a region off your (per-user) selection stack.", + privs = { worldedit = true }, + parse = function(params_text) + return true + end, + nodes_needed = function(name) + return 0 + end, + func = function(name) + local success, pos1, pos2 = worldeditadditions.spop(name) + if not success then return success, pos1 end + + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.marker_update(name) + + local new_count = worldeditadditions.scount(name) + local plural = "s are" + if new_count == 1 then plural = " is" end + + local region_text = worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name]) + + minetest.log("action", name .. " used //spush at "..region_text..". Stack height is now " .. new_count.." regions") + return true, "Region "..region_text.." pushed onto selection stack; "..new_count.." region"..plural.." now in the stack" + end +}) diff --git a/worldeditadditions_commands/commands/selectors/spush.lua b/worldeditadditions_commands/commands/selectors/spush.lua new file mode 100644 index 0000000..8c85fe0 --- /dev/null +++ b/worldeditadditions_commands/commands/selectors/spush.lua @@ -0,0 +1,32 @@ +-- ███████ ██████ ██ ██ ███████ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██████ ██ ██ ███████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ██████ ███████ ██ ██ +worldedit.register_command("spush", { + params = "", + description = "Pushes the currently defined region onto your (per-user) selection stack.", + privs = { worldedit = true }, + require_pos = 1, + parse = function(params_text) + return true + end, + nodes_needed = function(name) + return 0 + end, + func = function(name) + local success, msg = worldeditadditions.spush(name, worldedit.pos1[name], worldedit.pos2[name]) + if not success then + return success, msg + end + + local new_count = worldeditadditions.scount(name) + local plural = "s are" + if new_count == 1 then plural = " is" end + + local region_text = worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name]) + + minetest.log("action", name .. " used //spush at "..region_text..". Stack height is now " .. new_count.." regions") + return true, "Region "..region_text.." pushed onto selection stack; "..new_count.." region"..plural.." now in the stack" + end +}) diff --git a/worldeditadditions_commands/commands/selectors/sstack.lua b/worldeditadditions_commands/commands/selectors/sstack.lua new file mode 100644 index 0000000..6ff4cac --- /dev/null +++ b/worldeditadditions_commands/commands/selectors/sstack.lua @@ -0,0 +1,36 @@ +-- ███████ ███████ ████████ █████ ██████ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ███████ ██ ███████ ██ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ███████ ██ ██ ██ ██████ ██ ██ +worldedit.register_command("sstack", { + params = "", + description = "Displays the contents of your (per-user) selection stack.", + privs = { worldedit = true }, + parse = function(params_text) + return true + end, + nodes_needed = function(name) + return 0 + end, + func = function(name) + + local result = {"Stack contents for user ", name, ":\n"} + if not worldeditadditions.sstack[name] then + table.insert(result, "(empty)") + else + for i,item in ipairs(worldeditadditions.sstack[name]) do + table.insert(result, i) + table.insert(result, ": ") + table.insert(result, worldeditadditions.vector.tostring(item[1])) + table.insert(result, " - ") + table.insert(result, worldeditadditions.vector.tostring(item[2])) + table.insert(result, "\n") + end + table.insert(result, "========================\nTotal ") + table.insert(result, #worldeditadditions.sstack[name]) + table.insert(result, " items") + end + return true, table.concat(result, "") + end +}) diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index 425413c..75b85cf 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -44,6 +44,9 @@ dofile(we_c.modpath.."/commands/meta/ellipsoidapply.lua") -- dofile(we_c.modpath.."/commands/selectors/scol.lua") dofile(we_c.modpath.."/commands/selectors/srect.lua") -- dofile(we_c.modpath.."/commands/selectors/scube.lua") +dofile(we_c.modpath.."/commands/selectors/sstack.lua") +dofile(we_c.modpath.."/commands/selectors/spush.lua") +dofile(we_c.modpath.."/commands/selectors/spop.lua") dofile(we_c.modpath.."/commands/extra/saplingaliases.lua") dofile(we_c.modpath.."/commands/extra/basename.lua")