Finish initial //ellipsoidapply implementation

This commit is contained in:
Starbeamrainbowlabs 2020-09-20 21:19:29 +01:00
parent e0e64dc6b9
commit a6f5fe5123
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
5 changed files with 94 additions and 13 deletions

View file

@ -35,3 +35,5 @@ dofile(worldeditadditions.modpath.."/lib/count.lua")
dofile(worldeditadditions.modpath.."/lib/bonemeal.lua") dofile(worldeditadditions.modpath.."/lib/bonemeal.lua")
dofile(worldeditadditions.modpath.."/lib/forest.lua") dofile(worldeditadditions.modpath.."/lib/forest.lua")
dofile(worldeditadditions.modpath.."/lib/ellipsoidapply.lua")

View file

@ -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. --- 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 -- 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} pos1 The 1st position defining the region boundary
-- @param {Position} pos2 The 2nd positioon 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. -- @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) pos1, pos2 = worldedit.sort_pos(pos1, pos2)
-- pos2 will always have the highest co-ordinates now -- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area -- Fetch the nodes in the specified area
local manip_before, area_before = worldedit.manip_helpers.init(pos1, pos2) 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() func()
time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn
local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2) 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 = { local radius = {
x = (pos2.x - pos1.x) / 2, 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 z = pos2.z, pos1.z, -1 do
for y = pos2.y, pos1.y, -1 do for y = pos2.y, pos1.y, -1 do
for x = pos2.x, pos1.x, -1 do for x = pos2.x, pos1.x, -1 do
local comp_x = (x - e_centre.x) / radius.x local x_comp = (x - e_centre.x) / radius.x
local comp_y = (y - e_centre.y) / radius.y local y_comp = (y - e_centre.y) / radius.y
local comp_z = (z - e_centre.z) / radius.z 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 end
end end
@ -50,4 +64,7 @@ function worldeditadditions.ellipseapply(pos1, pos2, func)
-- No need to save - this function doesn't actually change anything -- No need to save - this function doesn't actually change anything
worldedit.manip_helpers.finish(manip_after, data_after) 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 end

View file

@ -95,7 +95,7 @@ worldedit.register_command("maze3d", {
params = "<replace_node> [<path_length> [<path_width> [<path_depth> [<seed>]]]]", params = "<replace_node> [<path_length> [<path_width> [<path_depth> [<seed>]]]]",
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).", 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 }, privs = { worldedit = true },
requre_pos = 2, require_pos = 2,
parse = function(params_text) parse = function(params_text)
local values = {parse_params_maze(params_text, true)} local values = {parse_params_maze(params_text, true)}
return unpack(values) return unpack(values)

View file

@ -0,0 +1,61 @@
-- ███████ ██ ██ ██ ██████ ███████ ███████ █████ ██████ ██████ ██ ██ ██
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- █████ ██ ██ ██ ██████ ███████ █████ ███████ ██████ ██████ ██ ████
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ███████ ███████ ███████ ██ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██
worldedit.register_command("ellipsoidapply", {
params = "<command_name> <args>",
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
})

View file

@ -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/multi.lua")
dofile(we_c.modpath.."/commands/meta/many.lua") dofile(we_c.modpath.."/commands/meta/many.lua")
dofile(we_c.modpath.."/commands/meta/subdivide.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 -- Don't registry the //bonemeal command if the bonemeal mod isn't present
if minetest.get_modpath("bonemeal") then if minetest.get_modpath("bonemeal") then