From a6f5fe512395c2a1f10d2ad3d148c63ff0f76f9f Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sun, 20 Sep 2020 21:19:29 +0100 Subject: [PATCH] Finish initial //ellipsoidapply implementation --- worldeditadditions/init.lua | 2 + .../{ellipseapply.lua => ellipsoidapply.lua} | 41 +++++++++---- worldeditadditions_commands/commands/maze.lua | 2 +- .../commands/meta/ellipsoidapply.lua | 61 +++++++++++++++++++ worldeditadditions_commands/init.lua | 1 + 5 files changed, 94 insertions(+), 13 deletions(-) rename worldeditadditions/lib/{ellipseapply.lua => ellipsoidapply.lua} (53%) create mode 100644 worldeditadditions_commands/commands/meta/ellipsoidapply.lua diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index 0c27906..3d24ea6 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -35,3 +35,5 @@ dofile(worldeditadditions.modpath.."/lib/count.lua") dofile(worldeditadditions.modpath.."/lib/bonemeal.lua") dofile(worldeditadditions.modpath.."/lib/forest.lua") + +dofile(worldeditadditions.modpath.."/lib/ellipsoidapply.lua") diff --git a/worldeditadditions/lib/ellipseapply.lua b/worldeditadditions/lib/ellipsoidapply.lua similarity index 53% rename from worldeditadditions/lib/ellipseapply.lua rename to worldeditadditions/lib/ellipsoidapply.lua index 5aeadf3..6012721 100644 --- a/worldeditadditions/lib/ellipseapply.lua +++ b/worldeditadditions/lib/ellipsoidapply.lua @@ -1,8 +1,14 @@ --- ███████ ██ ██ ██ ██████ ███████ ███████ █████ ██████ ██████ ██ ██ ██ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- █████ ██ ██ ██ ██████ ███████ █████ ███████ ██████ ██████ ██ ████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ███████ ███████ ██ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██ +-- ███████ ██ ██ ██ ██████ ███████ ██████ ██ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- █████ ██ ██ ██ ██████ ███████ ██ ██ ██ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ███████ ███████ ██ ██ ███████ ██████ ██ ██████ +-- +-- █████ ██████ ██████ ██ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██████ ██████ ██ ████ +-- ██ ██ ██ ██ ██ ██ +-- ██ ██ ██ ██ ███████ ██ --- Similar to cubeapply, except that it takes 2 positions and only keeps an ellipsoid-shaped area defined by the boundaries of the defined region. -- Takes a backup copy of the defined region, runs the given function, and then @@ -10,18 +16,21 @@ -- @param {Position} pos1 The 1st position defining the region boundary -- @param {Position} pos2 The 2nd positioon defining the region boundary -- @param {Function} func The function to call that performs the action in question. It is expected that the given function will accept no arguments. -function worldeditadditions.ellipseapply(pos1, pos2, func) +function worldeditadditions.ellipsoidapply(pos1, pos2, func) + local time_taken_all = worldeditadditions.get_ms_time() pos1, pos2 = worldedit.sort_pos(pos1, pos2) -- pos2 will always have the highest co-ordinates now -- Fetch the nodes in the specified area local manip_before, area_before = worldedit.manip_helpers.init(pos1, pos2) - local data_before = manip:get_data() + local data_before = manip_before:get_data() + local time_taken_fn = worldeditadditions.get_ms_time() func() + time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2) - local data_after = manip:get_data() + local data_after = manip_after:get_data() local radius = { x = (pos2.x - pos1.x) / 2, @@ -37,11 +46,16 @@ function worldeditadditions.ellipseapply(pos1, pos2, func) for z = pos2.z, pos1.z, -1 do for y = pos2.y, pos1.y, -1 do for x = pos2.x, pos1.x, -1 do - local comp_x = (x - e_centre.x) / radius.x - local comp_y = (y - e_centre.y) / radius.y - local comp_z = (z - e_centre.z) / radius.z + local x_comp = (x - e_centre.x) / radius.x + local y_comp = (y - e_centre.y) / radius.y + local z_comp = (z - e_centre.z) / radius.z - -- TODO finish this + local distance_mult = x_comp*x_comp + y_comp*y_comp + z_comp*z_comp + + -- Roll everything that's outside the ellipse back + if distance_mult > 1 then + data_after[area_after:index(x, y, z)] = data_before[area_before:index(x, y, z)] + end end end end @@ -50,4 +64,7 @@ function worldeditadditions.ellipseapply(pos1, pos2, func) -- No need to save - this function doesn't actually change anything worldedit.manip_helpers.finish(manip_after, data_after) + + time_taken_all = worldeditadditions.get_ms_time() - time_taken_all + return true, { all = time_taken_all, fn = time_taken_fn } end diff --git a/worldeditadditions_commands/commands/maze.lua b/worldeditadditions_commands/commands/maze.lua index 9e54b8e..fbd9cda 100644 --- a/worldeditadditions_commands/commands/maze.lua +++ b/worldeditadditions_commands/commands/maze.lua @@ -95,7 +95,7 @@ worldedit.register_command("maze3d", { params = " [ [ [ []]]]", description = "Generates a 3d maze covering the currently selected area (must be at least 3x3x3) with replace_node as the walls. Optionally takes a (integer) seed and the path length, width, and depth (see the documentation in the worldeditadditions README for more information).", privs = { worldedit = true }, - requre_pos = 2, + require_pos = 2, parse = function(params_text) local values = {parse_params_maze(params_text, true)} return unpack(values) diff --git a/worldeditadditions_commands/commands/meta/ellipsoidapply.lua b/worldeditadditions_commands/commands/meta/ellipsoidapply.lua new file mode 100644 index 0000000..dced192 --- /dev/null +++ b/worldeditadditions_commands/commands/meta/ellipsoidapply.lua @@ -0,0 +1,61 @@ +-- ███████ ██ ██ ██ ██████ ███████ ███████ █████ ██████ ██████ ██ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- █████ ██ ██ ██ ██████ ███████ █████ ███████ ██████ ██████ ██ ████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ███████ ███████ ██ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██ + +worldedit.register_command("ellipsoidapply", { + params = " ", + description = "Executes the given command (automatically prepending '//'), clipping the result with an ellipse given by the defined region.", + privs = { worldedit = true }, + require_pos = 2, + parse = function(params_text) + if params_text == "" then return false, "Error: No command specified." end + + local cmd_name, args_text = params_text:match("([^%s]+)%s+(.+)") + if not cmd_name then + return false, "Error: Invalid syntax." + end + + print("cmd_name", cmd_name, "args_text", args_text) + + -- Note that we search the worldedit commands here, not the minetest ones + local cmd_we = worldedit.registered_commands[cmd_name] + if cmd_we == nil then + return false, "Error: "..cmd_name.." isn't a valid command." + end + print("cmd require_pos", cmd_we.require_pos, "END") + if cmd_we.require_pos ~= 2 then + return false, "Error: The command "..cmd_name.." exists, but doesn't take 2 positions and so can't be used with //ellipsoidapply." + end + + -- Run parsing of target command + -- Lifted from cubeapply in WorldEdit + local args_parsed = {cmd_we.parse(args_text)} + if not table.remove(args_parsed, 1) then + return false, args_parsed[1] + end + + return true, cmd_we, args_parsed + end, + nodes_needed = function(name) + local pos1, pos2 = worldedit.sort_pos(worldedit.pos1[name], worldedit.pos2[name]) + return math.ceil(4/3 * math.pi * (pos2.x - pos1.x)/2 * (pos2.y - pos1.y)/2 * (pos2.z - pos1.z)/2) + end, + func = function(name, cmd, args_parsed) + if not minetest.check_player_privs(name, cmd.privs) then + return false, "Your privileges are insufficient to execute the command '"..cmd_name.."'." + end + + local success, stats_time = worldeditadditions.ellipsoidapply( + worldedit.pos1[name], worldedit.pos2[name], + function() + cmd.func(name, unpack(args_parsed)) + end, args + ) + local time_overhead = worldeditadditions.round((stats_time.fn / stats_time.all) * 100, 3) + + minetest.log("action", name.." used //ellipsoidapply at "..worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name]).." in "..worldeditadditions.human_time(stats_time.all)) + return true, "Complete in "..worldeditadditions.human_time(stats_time.all).." ("..worldeditadditions.human_time(stats_time.fn).." fn, "..time_overhead.."% ellipsoidapply overhead)" + end +}) diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index 5c18ed3..e91c3c5 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -37,6 +37,7 @@ dofile(we_c.modpath.."/commands/saplingaliases.lua") dofile(we_c.modpath.."/commands/meta/multi.lua") dofile(we_c.modpath.."/commands/meta/many.lua") dofile(we_c.modpath.."/commands/meta/subdivide.lua") +dofile(we_c.modpath.."/commands/meta/ellipsoidapply.lua") -- Don't registry the //bonemeal command if the bonemeal mod isn't present if minetest.get_modpath("bonemeal") then