From 429beb2e520bf4152bbcb569c8e998a4f922fcd8 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 9 Jun 2018 20:02:30 +0100 Subject: [PATCH] Add a hollowellipsoid command --- worldeditadditions/ellipsoid.lua | 27 ++++++++++++++---- worldeditadditions_commands/init.lua | 42 +++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/worldeditadditions/ellipsoid.lua b/worldeditadditions/ellipsoid.lua index 846ad7c..83820b6 100644 --- a/worldeditadditions/ellipsoid.lua +++ b/worldeditadditions/ellipsoid.lua @@ -1,9 +1,13 @@ --- Overlap command. Places a specified node on top of -- @module worldeditadditions.overlay -function worldedit.ellipsoid(position, radius, target_node) +function worldedit.ellipsoid(position, radius, target_node, hollow) -- position = { x, y, z } - + local hollow_inner_radius = { + x = radius.x - 1, + y = radius.y - 1, + z = radius.z - 1 + } -- Fetch the nodes in the specified area -- OPTIMIZE: We should be able to calculate a more efficient box-area here @@ -30,11 +34,24 @@ function worldedit.ellipsoid(position, radius, target_node) -- If we're inside the ellipse, then fill it in local x_comp, y_comp, z_comp = x/radius.x, y/radius.y, z/radius.z - if x_comp*x_comp + y_comp*y_comp + z_comp*z_comp <= 1 then + local ellipsoid_dist = x_comp*x_comp + y_comp*y_comp + z_comp*z_comp + if ellipsoid_dist <= 1 then + local place_ok = not hollow; - data[i] = node_id - count = count + 1 + if not place_ok then + -- It must be hollow! Do some additional calculations. + local hx_comp = x/hollow_inner_radius.x + local hy_comp = y/hollow_inner_radius.y + local hz_comp = z/hollow_inner_radius.z + + -- It's only ok to place it if it's outside our inner ellipse + place_ok = hx_comp*hx_comp + hy_comp*hy_comp + hz_comp*hz_comp >= 1 + end + if place_ok then + data[i] = node_id + count = count + 1 + end end diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index cb38280..ac8adbd 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -117,13 +117,7 @@ local function parse_params_ellipsoid(params_text) z = tonumber(radius_z) } - minetest.log("action", "Radius x: " .. radius_x) - minetest.log("action", "Radius y: " .. radius_y) - minetest.log("action", "Radius z: " .. radius_z) - - minetest.log("action", "Raw target node: " .. replace_node) replace_node = worldedit.normalize_nodename(replace_node) - minetest.log("action", "Normalised target node: " .. replace_node) return replace_node, radius end @@ -145,7 +139,7 @@ minetest.register_chatcommand("/ellipsoid", { end local start_time = os.clock() - local replaced = worldedit.ellipsoid(worldedit.pos1[name], radius, target_node) + local replaced = worldedit.ellipsoid(worldedit.pos1[name], radius, target_node, false) local time_taken = os.clock() - start_time worldedit.player_notify(name, replaced .. " nodes replaced in " .. time_taken .. "s") @@ -160,3 +154,37 @@ minetest.register_chatcommand("/ellipsoid", { return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z) end) }) + +-- TODO: This duplicates a lot of code. Perhaps we can trim it down a bit? +minetest.register_chatcommand("/hollowellipsoid", { + params = " ", + description = "Creates a 3D hollow ellipsoid with a radius of (rx, ry, rz) at pos1, filled with .", + privs = { worldedit = true }, + func = safe_region(function(name, params_text) + local target_node, radius = parse_params_ellipsoid(params_text) + + if not target_node then + worldedit.player_notify(name, "Error: Invalid node name.") + return false + end + if not radius then + worldedit.player_notify(name, "Error: Invalid radius(es).") + return false + end + + local start_time = os.clock() + local replaced = worldedit.ellipsoid(worldedit.pos1[name], radius, target_node, true) + local time_taken = os.clock() - start_time + + worldedit.player_notify(name, replaced .. " nodes replaced in " .. time_taken .. "s") + minetest.log("action", name .. " used //hollowellipsoid at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. replaced .. " nodes in " .. time_taken .. "s") + end, function(name, params_text) + local target_node, radius = parse_params_ellipsoid(params_text) + if not target_node or not radius then + worldedit.player_notify(name, "Error: Invalid input '" .. params_text .. "'. Try '/help /ellipsoid' to learn how to use this command.") + return 0 + end + + return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z) + end) +})