From 0573cd875588167369625b459290203cbb08fab3 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 24 Sep 2025 17:35:25 +0200 Subject: [PATCH] Genericize relative direction handling --- worldedit/cuboid.lua | 61 ++-------------------- worldedit_commands/cuboid.lua | 74 +++++++------------------- worldedit_commands/init.lua | 89 ++++++++++++++++++++++++++------ worldedit_commands/test/init.lua | 25 +++++++++ 4 files changed, 120 insertions(+), 129 deletions(-) diff --git a/worldedit/cuboid.lua b/worldedit/cuboid.lua index 5c52747..a467046 100644 --- a/worldedit/cuboid.lua +++ b/worldedit/cuboid.lua @@ -1,3 +1,6 @@ +-- FIXME: worldedit.pos1/2 is a concept of worldedit_commands only, so these functions here +-- are actually misplaced. + -- Expands or contracts the cuboid in all axes by amount (positive or negative) worldedit.cuboid_volumetric_expand = function(name, amount) local pos1 = worldedit.pos1[name] @@ -186,61 +189,3 @@ worldedit.marker_get_closest_to_axis = function(name, axis, direction) return nil end end - - --- Translates up, down, left, right, front, back to their corresponding axes and --- directions according to faced direction -worldedit.translate_direction = function(name, direction) - local axis, dir = worldedit.player_axis(name) - local resaxis, resdir - - if direction == "up" then - return 'y', 1 - end - - if direction == "down" then - return 'y', -1 - end - - if direction == "front" then - if axis == "y" then - resaxis = nil - resdir = nil - else - resaxis = axis - resdir = dir - end - end - - if direction == "back" then - if axis == "y" then - resaxis = nil - resdir = nil - else - resaxis = axis - resdir = -dir - end - end - - if direction == "left" then - if axis == 'x' then - resaxis = 'z' - resdir = dir - elseif axis == 'z' then - resaxis = 'x' - resdir = -dir - end - end - - if direction == "right" then - if axis == 'x' then - resaxis = 'z' - resdir = -dir - elseif axis == 'z' then - resaxis = 'x' - resdir = dir - end - end - - return resaxis, resdir -end diff --git a/worldedit_commands/cuboid.lua b/worldedit_commands/cuboid.lua index d8d017a..9b463c6 100644 --- a/worldedit_commands/cuboid.lua +++ b/worldedit_commands/cuboid.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("worldedit_commands") +local VALID_DIR = worldedit.valid_directions + worldedit.register_command("outset", { params = "[h/v] ", description = S("Outset the selected region."), @@ -7,7 +9,7 @@ worldedit.register_command("outset", { privs = {worldedit=true}, require_pos = 2, parse = function(param) - local find, _, dir, amount = param:find("(%a*)%s*([+-]?%d+)") + local find, _, dir, amount = param:find("^(%a*)%s+([+-]?%d+)$") if find == nil then return false end @@ -47,7 +49,7 @@ worldedit.register_command("inset", { privs = {worldedit=true}, require_pos = 2, parse = function(param) - local find, _, dir, amount = param:find("(%a*)%s*([+-]?%d+)") + local find, _, dir, amount = param:find("^(%a*)%s+([+-]?%d+)$") if find == nil then return false end @@ -79,29 +81,21 @@ worldedit.register_command("inset", { worldedit.register_command("shift", { - params = "x/y/z/?/up/down/left/right/front/back [+/-]", + params = tostring(VALID_DIR) .. " [+/-]", description = S("Shifts the selection area without moving its contents"), category = S("Region operations"), privs = {worldedit=true}, require_pos = 2, parse = function(param) - local find, _, direction, amount = param:find("([%?%l]+)%s*([+-]?%d+)") - if find == nil then + local find, _, direction, amount = param:find("^([^%s]+)%s+([+-]?%d+)$") + if find == nil or not VALID_DIR[direction] then return false end return true, direction, tonumber(amount) end, func = function(name, direction, amount) - local axis, dir - if direction == "x" or direction == "y" or direction == "z" then - axis, dir = direction, 1 - elseif direction == "?" then - axis, dir = worldedit.player_axis(name) - else - axis, dir = worldedit.translate_direction(name, direction) - end - + local axis, dir = worldedit.player_direction(name, direction) if axis == nil or dir == nil then return false, S("Invalid if looking straight up or down") end @@ -115,15 +109,15 @@ worldedit.register_command("shift", { worldedit.register_command("expand", { - params = "[+/-]x/y/z/?/up/down/left/right/front/back [reverse amount]", + params = "[+/-]" .. tostring(VALID_DIR) .. " [reverse amount]", description = S("Expands the selection in the selected absolute or relative axis"), category = S("Region operations"), privs = {worldedit=true}, require_pos = 2, parse = function(param) local find, _, sign, direction, amount, - rev_amount = param:find("([+-]?)([%?%l]+)%s*(%d+)%s*(%d*)") - if find == nil then + rev_amount = param:find("^([+-]?)([^%s]+)%s+(%d+)%s*(%d*)$") + if find == nil or not VALID_DIR[direction] then return false end @@ -134,24 +128,10 @@ worldedit.register_command("expand", { return true, sign, direction, tonumber(amount), tonumber(rev_amount) end, func = function(name, sign, direction, amount, rev_amount) - local absolute = direction:find("[xyz?]") - local dir, axis - - if absolute == nil then - axis, dir = worldedit.translate_direction(name, direction) - - if axis == nil or dir == nil then - return false, S("Invalid if looking straight up or down") - end - else - if direction == "?" then - axis, dir = worldedit.player_axis(name) - else - axis = direction - dir = 1 - end + local axis, dir = worldedit.player_direction(name, direction) + if axis == nil or dir == nil then + return false, S("Invalid if looking straight up or down") end - if sign == "-" then dir = -dir end @@ -165,15 +145,15 @@ worldedit.register_command("expand", { worldedit.register_command("contract", { - params = "[+/-]x/y/z/?/up/down/left/right/front/back [reverse amount]", + params = "[+/-]" .. tostring(VALID_DIR) .. " [reverse amount]", description = S("Contracts the selection in the selected absolute or relative axis"), category = S("Region operations"), privs = {worldedit=true}, require_pos = 2, parse = function(param) local find, _, sign, direction, amount, - rev_amount = param:find("([+-]?)([%?%l]+)%s*(%d+)%s*(%d*)") - if find == nil then + rev_amount = param:find("^([+-]?)([^%s]+)%s+(%d+)%s*(%d*)$") + if find == nil or not VALID_DIR[direction] then return false end @@ -184,24 +164,10 @@ worldedit.register_command("contract", { return true, sign, direction, tonumber(amount), tonumber(rev_amount) end, func = function(name, sign, direction, amount, rev_amount) - local absolute = direction:find("[xyz?]") - local dir, axis - - if absolute == nil then - axis, dir = worldedit.translate_direction(name, direction) - - if axis == nil or dir == nil then - return false, S("Invalid if looking straight up or down") - end - else - if direction == "?" then - axis, dir = worldedit.player_axis(name) - else - axis = direction - dir = 1 - end + local axis, dir = worldedit.player_direction(name, direction) + if axis == nil or dir == nil then + return false, S("Invalid if looking straight up or down") end - if sign == "-" then dir = -dir end diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index d645da8..a7aa8c8 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -143,22 +143,6 @@ function worldedit.register_command(name, def) worldedit.registered_commands[name] = def end - -do - local modpath = minetest.get_modpath("worldedit_commands") - for _, name in ipairs({ - "code", "cuboid", "manipulations", "marker", "nodename", "primitives", - "region", "schematics", "transform", "wand" - }) do - dofile(modpath .. "/" .. name .. ".lua") - end - - if worldedit.register_test then - dofile(modpath .. "/test/init.lua") - end -end - - -- Notifies a player of something related to WorldEdit. -- Message types: -- "error" = An operation did not work as expected. @@ -203,7 +187,63 @@ function worldedit.player_axis(name) return "z", dir.z > 0 and 1 or -1 end --- Wrapper for the engine's parse_coordinates +-- Look-up table of valid directions (for worldedit.player_direction) +-- Can be stringified for usage in help texts +-- @note Not part of API +worldedit.valid_directions = setmetatable({ + x = true, y = true, z = true, + ["?"] = true, + up = true, down = true, + front = true, back = true, + left = true, right = true, +}, { + __tostring = function() + return "x/y/z/?/up/down/left/right/front/back" + end +}) + +-- Accepts a valid directions as above +-- @return axis ("x", "y", or "z") and the sign (1 or -1) *or* nil for invalid combinations +-- @note Not part of API +worldedit.player_direction = function(name, str) + if str == "x" or str == "y" or str == "z" then + return str, 1 + elseif str == "up" then + return "y", 1 + elseif str == "down" then + return "y", -1 + end + + local axis, dir = worldedit.player_axis(name) + + if str == "?" then + return axis, dir + elseif str == "front" then + if axis ~= "y" then + return axis, dir + end + elseif str == "back" then + if axis ~= "y" then + return axis, -dir + end + elseif str == "left" then + if axis == "x" then + return "z", dir + elseif axis == "z" then + return "x", -dir + end + elseif str == "right" then + if axis == "x" then + return "z", -dir + elseif axis == "z" then + return "x", dir + end + end + + return nil, nil +end + +-- Wrapper for the engine"s parse_coordinates -- @return vector or nil -- @note Not part of API function worldedit.parse_coordinates(x, y, z, player_name) @@ -348,3 +388,18 @@ worldedit.register_command("reset", { return true, S("region reset") end, }) + +-- Load the other parts +do + local modpath = minetest.get_modpath("worldedit_commands") + for _, name in ipairs({ + "code", "cuboid", "manipulations", "marker", "nodename", "primitives", + "region", "schematics", "transform", "wand" + }) do + dofile(modpath .. "/" .. name .. ".lua") + end + + if worldedit.register_test then + dofile(modpath .. "/test/init.lua") + end +end diff --git a/worldedit_commands/test/init.lua b/worldedit_commands/test/init.lua index 17b3fb8..0cf6c38 100644 --- a/worldedit_commands/test/init.lua +++ b/worldedit_commands/test/init.lua @@ -63,6 +63,31 @@ register_test("//inset", make_parsing_test("inset", { "v foo", })) +register_test("//shift", make_parsing_test("shift", { + "x 1", + "x -4", + "back 1", + "? 1", +}, { + "+z 1212", + "-z 9", + "xx -5", + "?? 123", +})) + +register_test("//expand", make_parsing_test("expand", { + "x 1", + "z 1 2", + "? 1", + "+? 1", + "+left 1", + "-right 1", +}, { + "x -4", + "? 4 -333", + "stupid 5 5", +})) + register_test("//cubeapply", make_parsing_test("cubeapply", { "2 orient 90", "2 3 4 orient 90",