From 8d213d32a092ec03dca17ada9217a87656bd2b18 Mon Sep 17 00:00:00 2001 From: Daniel Sosa Date: Sat, 3 Jan 2015 19:46:59 -0600 Subject: [PATCH] refactor code for mantainability and reusability. Start of chat command refactor. Implement /outset. --- worldedit_commands/area.lua | 454 ------------------------------- worldedit_commands/cuboid.lua | 95 +++++++ worldedit_commands/cuboidapi.lua | 248 +++++++++++++++++ worldedit_commands/init.lua | 2 +- 4 files changed, 344 insertions(+), 455 deletions(-) delete mode 100644 worldedit_commands/area.lua create mode 100644 worldedit_commands/cuboid.lua create mode 100644 worldedit_commands/cuboidapi.lua diff --git a/worldedit_commands/area.lua b/worldedit_commands/area.lua deleted file mode 100644 index e9e5e73..0000000 --- a/worldedit_commands/area.lua +++ /dev/null @@ -1,454 +0,0 @@ -minetest.register_chatcommand( - "/outset", - { - params = " [h|v]", - description = "outset the selection", - privs = {worldedit=true}, - func = function(name, param) - local find, _, amount, dir = param:find("^(%d+)[%s+]?([hv]?)$") - - if find == nil then - return false, "invalid usage: " .. param - end - - local pos1 = worldedit.pos1[name] - local pos2 = worldedit.pos2[name] - - if pos1 == nil or pos2 == nil then - return false, "Undefined region. Region must be defined beforehand." - end - - local dirs = worldedit.get_outset_directions(pos1, pos2) - - if dir == 'h' then - worldedit.move_marker(name, 1, 'x', amount * dirs.x1) - worldedit.move_marker(name, 1, 'z', amount * dirs.z1) - - worldedit.move_marker(name, 2, 'x', amount * dirs.x2) - worldedit.move_marker(name, 2, 'z', amount * dirs.z2) - message = "area outset by " .. amount .. " blocks horizontally" - elseif dir == 'v' then - worldedit.move_marker(name, 1, 'y', amount * dirs.y1) - worldedit.move_marker(name, 2, 'y', amount * dirs.y2) - message = "area outset by " .. amount .. " blocks vertically" - else - worldedit.move_marker(name, 1, 'x', amount * dirs.x1) - worldedit.move_marker(name, 1, 'y', amount * dirs.y1) - worldedit.move_marker(name, 1, 'z', amount * dirs.z1) - - worldedit.move_marker(name, 2, 'x', amount * dirs.x2) - worldedit.move_marker(name, 2, 'y', amount * dirs.y2) - worldedit.move_marker(name, 2, 'z', amount * dirs.z2) - message = "area outset by " .. amount .. " blocks in all axes" - end - - worldedit.update_markers(name) - return true, message - end, - } -) - -minetest.register_chatcommand( - "/inset", - { - params = " [h|v]", - description = "inset the selection", - privs = {worldedit=true}, - func = function(name, param) - local find, _, amount, dir = param:find("^(%d+)[%s+]?([hv]?)$") - - if find == nil then - return false, "invalid usage: " .. param - end - - local pos1 = worldedit.pos1[name] - local pos2 = worldedit.pos2[name] - - if pos1 == nil or pos2 == nil then - return false, "Undefined region. Region must be defined beforehand." - end - - local dirs = worldedit.get_outset_directions(pos1, pos2) - amount = -amount - - if dir == 'h' then - worldedit.move_marker(name, 1, 'x', amount * dirs.x1) - worldedit.move_marker(name, 1, 'z', amount * dirs.z1) - - worldedit.move_marker(name, 2, 'x', amount * dirs.x2) - worldedit.move_marker(name, 2, 'z', amount * dirs.z2) - message = "area inset by " .. amount .. " blocks horizontally" - elseif dir == 'v' then - worldedit.move_marker(name, 1, 'y', amount * dirs.y1) - worldedit.move_marker(name, 2, 'y', amount * dirs.y2) - message = "area inset by " .. amount .. " blocks vertically" - else - worldedit.move_marker(name, 1, 'x', amount * dirs.x1) - worldedit.move_marker(name, 1, 'y', amount * dirs.y1) - worldedit.move_marker(name, 1, 'z', amount * dirs.z1) - - worldedit.move_marker(name, 2, 'x', amount * dirs.x2) - worldedit.move_marker(name, 2, 'y', amount * dirs.y2) - worldedit.move_marker(name, 2, 'z', amount * dirs.z2) - message = "area inset by " .. amount .. " blocks in all axes" - end - - worldedit.update_markers(name) - return true, message - end, - } -) - -worldedit.get_outset_directions = function(mark1, mark2) - if mark1 == nil or mark2 == nil then return - end - - local dirs = - { - x1 = 0, - x2 = 0, - y1 = 0, - y2 = 0, - z1 = 0, - z2 = 0 - } - - if mark1.x < mark2.x then - dirs.x1 = -1 - dirs.x2 = 1 - else - dirs.x1 = 1 - dirs.x2 = -1 - end - - if mark1.y < mark2.y then - dirs.y1 = -1 - dirs.y2 = 1 - else - dirs.y1 = 1 - dirs.y2 = -1 - end - - if mark1.z < mark2.z then - dirs.z1 = -1 - dirs.z2 = 1 - else - dirs.z1 = 1 - dirs.z2 = -1 - end - - return dirs -end - - -minetest.register_chatcommand( - "/shift", - { - params = " [up|down|left|right|front|back]", - description = "Moves the selection region. Does not move contents.", - privs = {worldedit=true}, - func = function(name, param) - local pos1 = worldedit.pos1[name] - local pos2 = worldedit.pos2[name] - local find, _, amount, direction = param:find("(%d+)%s*(%l*)") - - if find == nil then - worldedit.player_notify(name, "invalid usage: " .. param) - return - end - - if pos1 == nil or pos2 == nil then - worldedit.player_notify(name, "Undefined region. Region must be defined beforehand.") - return - end - - local axis, dirsign - - if direction ~= "" then - axis, dirsign = worldedit.translate_direction(name, direction) - else - axis, dirsign = worldedit.player_axis(name) - end - - if axis == nil or dirsign == nil then - return false, "Invalid usage: " .. param - end - - worldedit.move_marker(name, 1, axis, amount * dirsign) - worldedit.move_marker(name, 2, axis, amount * dirsign) - worldedit.update_markers(name) - - worldedit.player_notify(name, "Area shifted by " .. amount .. " in " .. direction .. " axis") - end, - } -) - -minetest.register_chatcommand( - "/expand", - { - params = " [reverse-amount] [up|down|left|right|front|back]", - description = "expand the selection in one or two directions at once", - privs = {worldedit=true}, - func = function(name, param) - local find, _, amount, arg2, arg3 = param:find("(%d+)%s*(%w*)%s*(%l*)") - - if find == nil then - worldedit.player_notify(name, "invalid use: " .. param) - return - end - - if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then - worldedit.player_notify(name, "Undefined region. Region must be defined beforehand.") - return - end - - local axis, direction, mark - - axis, direction = worldedit.player_axis(name) - mark = worldedit.get_marker_in_axis(name, axis, direction) - - if arg3 ~= "" then - axis, direction = worldedit.translate_direction(name, arg3) - mark = worldedit.get_marker_in_axis(name, axis, direction) - end - - if arg2 ~= "" then - local tmp = tonumber(arg2) - - if tmp == nil then - axis, direction = worldedit.translate_direction(name, arg2) - mark = worldedit.get_marker_in_axis(name, axis, direction) - else - local tmpmark - if mark == 1 then - tmpmark = 2 - else - tmpmark = 1 - end - - if axis == nil or direction == nil then - return false, "Invalid use: " .. param - end - - worldedit.move_marker(name, tmpmark, axis, tmp * direction * -1) - end - end - - if axis == nil or direction == nil then - return false, "Invalid use: " .. param - end - - worldedit.move_marker(name, mark, axis, amount * direction) - worldedit.update_markers(name) - worldedit.player_notify(name, "Area expanded by " .. amount) - end, - } -) - -minetest.register_chatcommand( - "/contract", - { - params = " [reverse-amount] [up|down|left|right|front|back]", - description = "contract the selection in one or two directions at once", - privs = {worldedit=true}, - func = function(name, param) - local find, _, amount, arg2, arg3 = param:find("(%d+)%s*(%w*)%s*(%l*)") - - if find == nil then - worldedit.player_notify(name, "invalid use: " .. param) - return - end - - if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then - worldedit.player_notify(name, "Undefined region. Region must be defined beforehand.") - return - end - - local axis, direction, mark - - axis, direction = worldedit.player_axis(name) - mark = worldedit.get_marker_in_axis(name, axis, direction) - - if arg3 ~= "" then - axis, direction = worldedit.translate_direction(name, arg3) - mark = worldedit.get_marker_in_axis(name, axis, direction) - end - - if arg2 ~= "" then - local tmp = tonumber(arg2) - - if tmp == nil then - axis, direction = worldedit.translate_direction(name, arg2) - mark = worldedit.get_marker_in_axis(name, axis, direction) - else - local tmpmark - if mark == 1 then - tmpmark = 2 - else - tmpmark = 1 - end - - if axis == nil or direction == nil then - return false, "Invalid use: " .. param - end - - worldedit.move_marker(name, tmpmark, axis, tmp * direction) - end - end - - if axis == nil or direction == nil then - return false, "Invalid use: " .. param - end - - worldedit.move_marker(name, mark, axis, amount * direction * -1) - worldedit.update_markers(name) - worldedit.player_notify(name, "Area contracted by " .. amount) - end, - } -) - - --- Return the marker that is closest to the player -worldedit.get_closest_marker = function(name) - local playerpos = minetest.get_player_by_name(name):getpos() - - local dist1 = vector.distance(playerpos, worldedit.pos1[name]) - local dist2 = vector.distance(playerpos, worldedit.pos2[name]) - - if dist1 < dist2 then - return 1 - else - return 2 - end -end - - --- returns which marker is closest to the specified axis and direction -worldedit.get_marker_in_axis = function(name, axis, direction) - local pos1 = {x = 0, y = 0, z = 0} - local pos2 = {x = 0, y = 0, z = 0} - - if direction ~= 1 and direction ~= -1 then - return nil - end - - if axis == 'x' then - pos1.x = worldedit.pos1[name].x * direction - pos2.x = worldedit.pos2[name].x * direction - if pos1.x > pos2.x then - return 1 - else - return 2 - end - elseif axis == 'y' then - pos1.y = worldedit.pos1[name].y * direction - pos2.y = worldedit.pos2[name].y * direction - if pos1.y > pos2.y then - return 1 - else - return 2 - end - elseif axis == 'z' then - pos1.z = worldedit.pos1[name].z * direction - pos2.z = worldedit.pos2[name].z * direction - if pos1.z > pos2.z then - return 1 - else - return 2 - end - else - minetest.debug("worldedit.get_marker_in_axis: invalid axis.") - end -end - --- Moves the selected marker in a single axis by amount nodes -worldedit.move_marker = function(name, marker, axis, amount) - local pos1 = worldedit.pos1[name] - local pos2 = worldedit.pos2[name] - - if marker == 1 then - if axis == 'x' then - worldedit.pos1[name].x = pos1.x + amount - elseif axis == 'y' then - worldedit.pos1[name].y = pos1.y + amount - elseif axis == 'z' then - worldedit.pos1[name].z = pos1.z + amount - else - minetest.debug("worldedit: Invalid axis in move_marker.") - end - elseif marker == 2 then - if axis == 'x' then - worldedit.pos2[name].x = pos2.x + amount - elseif axis == 'y' then - worldedit.pos2[name].y = pos2.y + amount - elseif axis == 'z' then - worldedit.pos2[name].z = pos2.z + amount - else - minetest.debug("worldedit: Invalid axis in move_marker.") - end - else - minetest.debug("Bad marker id at worldedit.move_marker") - end -end - --- Updates the location ingame of the markers -worldedit.update_markers = function(name, marker) - if marker == nil then - worldedit.mark_pos1(name) - worldedit.mark_pos2(name) - elseif marker == 1 then - worldedit.mark_pos1(name) - elseif marker == 2 then - worldedit.mark_pos2(name) - else - minetest.debug("worldedit: Invalid execution of function update_markers") - 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 - resaxis = axis - resdir = dir - end - - if direction == "back" then - resaxis = axis - resdir = -dir - 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 new file mode 100644 index 0000000..1af5b3b --- /dev/null +++ b/worldedit_commands/cuboid.lua @@ -0,0 +1,95 @@ +minetest.register_chatcommand("/outset", { + params = " [h|v]", + description = "outset the selection", + privs = {worldedit=true}, + func = function(name, param) + local find, _, amount, dir = param:find("^(%d+)[%s+]?([hv]?)$") + + if find == nil then + return false, "invalid usage: " .. param + end + + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, + "Undefined region. Region must be defined beforehand." + end + + if dir == "" then + assert(worldedit.cuboid_volumetricexpand(name, amount)) + elseif dir == "h" then + assert(worldedit.cuboid_linealexpand(name, 'x', 1, amount)) + assert(worldedit.cuboid_linealexpand(name, 'x', -1, amount)) + assert(worldedit.cuboid_linealexpand(name, 'z', 1, amount)) + assert(worldedit.cuboid_linealexpand(name, 'z', -1, amount)) + elseif dir == "v" then + assert(worldedit.cuboid_linealexpand(name, 'y', 1, amount)) + assert(worldedit.cuboid_linealexpand(name, 'y', -1, amount)) + else + return false, "Unknown error" + end + + worldedit.marker_update(name) + return true, "Region outset by " .. amount .. " blocks" + end, + } +) + + +minetest.register_chatcommand( + "/shift", + { + params = " [up|down|left|right|front|back]", + description = "Moves the selection region. Does not move contents.", + privs = {worldedit=true}, + func = function(name, param) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + local find, _, amount, direction = param:find("(%d+)%s*(%l*)") + + if find == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, + "Undefined region. Region must be defined beforehand.") + return + end + + + end, + } +) + +minetest.register_chatcommand( + "/expand", + { + params = " [reverse-amount] [up|down|left|right|front|back]", + description = "expand the selection in one or two directions at once", + privs = {worldedit=true}, + func = function(name, param) + local find, _, amount, arg2, arg3 = param:find("(%d+)%s*(%w*)%s*(%l*)") + + if find == nil then + worldedit.player_notify(name, "invalid use: " .. param) + return + end + + if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then + worldedit.player_notify(name, + "Undefined region. Region must be defined beforehand.") + return + end + + + end, + } +) + + +dofile(minetest.get_modpath("worldedit_commands") .. "/cuboidapi.lua") + diff --git a/worldedit_commands/cuboidapi.lua b/worldedit_commands/cuboidapi.lua new file mode 100644 index 0000000..37194e4 --- /dev/null +++ b/worldedit_commands/cuboidapi.lua @@ -0,0 +1,248 @@ +-- Expands or contracts the cuboid in all axes by amount (positive or negative) +worldedit.cuboid_volumetricexpand = function(name, amount) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, "Undefined cuboid" + end + + local delta1 = vector.new() + local delta2 = vector.new() + local deltadir1 + local deltadir2 + + delta1 = vector.add(delta1, amount) + delta2 = vector.add(delta2, amount) + deltadir1, deltadir2 = worldedit.get_expansion_directions(pos1, pos2) + delta1 = vector.multiply(delta1, deltadir1) + delta2 = vector.multiply(delta2, deltadir2) + worldedit.pos1[name] = vector.add(pos1, delta1) + worldedit.pos2[name] = vector.add(pos2, delta2) + + return true +end + + +-- Expands or contracts the cuboid in a single axis by amount (positive or negative) +worldedit.cuboid_linealexpand = function(name, axis, direction, amount) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, "undefined cuboid" + end + + if direction ~= 1 and direction ~= -1 then + return false, "invalid marker" + end + + local marker = worldedit.marker_get_closest_to_axis(name, axis, direction) + local deltavect = vector.new() + + if axis == 'x' then + deltavect.x = amount * direction + elseif axis == 'y' then + deltavect.y = amount * direction + elseif axis == 'z' then + deltavect.z = amount * direction + else + return false, "invalid axis" + end + + worldedit.marker_move(name, marker, deltavect) + return true +end + + +-- Shifts the cuboid by '+-amount' in axis 'axis' +worldedit.cuboid_shift = function(name, axis, amount) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, "undefined cuboid" + end + + if axis == 'x' then + pos1.x = pos1.x + amount + pos2.x = pos2.x + amount + elseif axis == 'y' then + pos1.y = pos1.y + amount + pos2.y = pos2.y + amount + elseif axis == 'z' then + pos1.z = pos1.z + amount + pos2.z = pos2.z + amount + else + return false, "invalid axis" + end + + return true +end + + +-- Moves the location of a single marker by adding deltavector +worldedit.marker_move = function(name, marker, deltavector) + if marker ~= 1 and marker ~= 2 then + return false + end + + if marker == 1 then + local pos = worldedit.pos1[name] + worldedit.pos1[name] = vector.add(deltavector, pos) + else + local pos = worldedit.pos2[name] + worldedit.pos2[name] = vector.add(deltavector, pos) + end + + return true +end + +-- Updates the location ingame of the markers +worldedit.marker_update = function(name, marker) + if marker == nil then + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + elseif marker == 1 then + worldedit.mark_pos1(name) + elseif marker == 2 then + worldedit.mark_pos2(name) + else + minetest.debug( + "worldedit: Invalid execution of function update_markers") + end +end + + +-- Returns two vectors with the directions for volumetric expansion +worldedit.get_expansion_directions = function(mark1, mark2) + if mark1 == nil or mark2 == nil then + return + end + local dir1 = vector.new() + local dir2 = vector.new() + + if mark1.x < mark2.x then + dir1.x = -1 + dir2.x = 1 + else + dir1.x = 1 + dir2.x = -1 + end + if mark1.y < mark2.y then + dir1.y = -1 + dir2.y = 1 + else + dir1.y = 1 + dir2.y = -1 + end + if mark1.z < mark2.z then + dir1.z = -1 + dir2.z = 1 + else + dir1.z = 1 + dir2.z = -1 + end + return dir1, dir2 +end + + +-- Return the marker that is closest to the player +worldedit.marker_get_closest_to_player = function(name) + local playerpos = minetest.get_player_by_name(name):getpos() + local dist1 = vector.distance(playerpos, worldedit.pos1[name]) + local dist2 = vector.distance(playerpos, worldedit.pos2[name]) + + if dist1 < dist2 then + return 1 + else + return 2 + end +end + + +-- Returns the closest marker to the specified axis and direction +worldedit.marker_get_closest_to_axis = function(name, axis, direction) + local pos1 = vector.new() + local pos2 = vector.new() + + if direction ~= 1 and direction ~= -1 then + return nil + end + + if axis == 'x' then + pos1.x = worldedit.pos1[name].x * direction + pos2.x = worldedit.pos2[name].x * direction + if pos1.x > pos2.x then + return 1 + else + return 2 + end + elseif axis == 'y' then + pos1.y = worldedit.pos1[name].y * direction + pos2.y = worldedit.pos2[name].y * direction + if pos1.y > pos2.y then + return 1 + else + return 2 + end + elseif axis == 'z' then + pos1.z = worldedit.pos1[name].z * direction + pos2.z = worldedit.pos2[name].z * direction + if pos1.z > pos2.z then + return 1 + else + return 2 + end + else + 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 + resaxis = axis + resdir = dir + end + + if direction == "back" then + resaxis = axis + resdir = -dir + 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 \ No newline at end of file diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 30e6f9a..21a6af3 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -1183,4 +1183,4 @@ minetest.register_chatcommand("/clearobjects", { end), }) -dofile(minetest.get_modpath("worldedit_commands") .. "/area.lua") +dofile(minetest.get_modpath("worldedit_commands") .. "/cuboid.lua")