Add //dome+

Improvements oveer //dome:

 - Allow customising the direction it points in
 - Allow multiple pointing directions at once to give the effect of 
creating multiple domes on top of each other in a single command (it's 
actually implemented as an implicit union, and doesn't actually call 
wea.dome more than once).
This commit is contained in:
Starbeamrainbowlabs 2022-05-15 15:27:43 +01:00
parent a99cef7bf9
commit 04e971e12d
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
6 changed files with 179 additions and 0 deletions

View file

@ -5,6 +5,7 @@ Note to self: See the bottom of this file for the release template text.
## v1.14: The untitled update (unreleased)
- Add `//dome+`, which allows you to change the direction the dome is pointing in, and also create multiple domes at once
- Migrate from `depends.txt` to `mod.conf`

View file

@ -172,6 +172,20 @@ Generates both square and circular spiral shapes with the given `<replace_node>`
```
### `//dome+ <radius> <replace_node> [<pointing_dir:x|y|z|-x|-y|-z|?|front|back|left|right|up|down> ...]`
Creates a dome shape (i.e. a hemisphere; half a sphere) with a specified radius of the defined node, optionally specifying the direction it should be pointing in (defaults to the positive y direction).
For example, `//dome+ 5 stone y` creates a dome shape pointing upwards, but `//dome+ 5 stone -y` creates a dome shape pointing downwards.
Multiple pointing direction axes can be chained together to create multiple domes on top of each other. Multiple conflicting directions will cancel each other out.
```
//dome+ 5 stone y
//dome+ 10 diamond -x
//dome+ 25 cactus y z
//dome+ 9 dirt x y z
```
## Misc
<!--

View file

@ -58,6 +58,7 @@ dofile(wea.modpath.."/lib/scale_down.lua")
dofile(wea.modpath.."/lib/scale.lua")
dofile(wea.modpath.."/lib/spiral_square.lua")
dofile(wea.modpath.."/lib/spiral_circle.lua")
dofile(wea.modpath.."/lib/dome.lua")
dofile(wea.modpath.."/lib/conv/conv.lua")
dofile(wea.modpath.."/lib/erode/erode.lua")
dofile(wea.modpath.."/lib/noise/init.lua")

View file

@ -0,0 +1,72 @@
local wea = worldeditadditions
local Vector3 = wea.Vector3
-- ██████ ██████ ███ ███ ███████
-- ██ ██ ██ ██ ████ ████ ██
-- ██ ██ ██ ██ ██ ████ ██ █████
-- ██ ██ ██ ██ ██ ██ ██ ██
-- ██████ ██████ ██ ██ ███████
--- Creates a dome shape with the given node, optionally specifying the
-- direction the point should point.
-- @param pos Vector3 The central point to start drawing the dome from.
-- @param radius number The radius of the dome to create.
-- @param replace_node string The fully qualified name of the node to use to make the dome with.
-- @parram pointing_dir Vector3 Optional. The direction the dome should point. Defaults to (0, 1, 0). See also wea.parse.axis_name.
function worldeditadditions.dome(pos, radius, replace_node, pointing_dir)
pos = Vector3.clone(pos)
local pos1 = pos - radius
local pos2 = pos + radius
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
local data = manip:get_data()
local node_id_replace = minetest.get_content_id(replace_node)
local radius_sq = radius * radius
local centrepoint = Vector3.mean(pos1, pos2)
local replaced = 0
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 distance_sq = (Vector3.new(x, y, z) - centrepoint):length_squared()
if distance_sq < radius_sq then
-- It's inside the radius, but we're still not sure given this is a dome and not a sphere
local should_include = false
if x < centrepoint.x and pointing_dir.x < 0 then
should_include = true
end
if x > centrepoint.x and pointing_dir.x > 0 then
should_include = true
end
if y < centrepoint.y and pointing_dir.y < 0 then
should_include = true
end
if y > centrepoint.y and pointing_dir.y > 0 then
should_include = true
end
if z < centrepoint.z and pointing_dir.z < 0 then
should_include = true
end
if z > centrepoint.z and pointing_dir.z > 0 then
should_include = true
end
if should_include then
data[area:index(x, y, z)] = node_id_replace
replaced = replaced + 1
end
end
end
end
end
-- Save the modified nodes back to disk & return
worldedit.manip_helpers.finish(manip, data)
return true, replaced
end

View file

@ -0,0 +1,90 @@
local wea = worldeditadditions
local Vector3 = wea.Vector3
local function parse_stage2(name, parts)
local result = Vector3.new()
for i,axis_name in ipairs(parts) do
local success, result_this = wea.parse.axis_name(axis_name, wea.player_dir(name))
if not success then return success, result_this end
result = result + result_this
end
result = result:clamp(Vector3.new(-1, -1, -1), Vector3.new(1, 1, 1))
if result.length == 0 then
return false, "Refusing to create a dome with no distinct pointing direction."
end
return true, result
end
-- ██████ ██████ ███ ███ ███████
-- ██ ██ ██ ██ ████ ████ ██
-- ██ ██ ██ ██ ██ ████ ██ █████
-- ██ ██ ██ ██ ██ ██ ██ ██
-- ██████ ██████ ██ ██ ███████
worldedit.register_command("dome+", { -- TODO: Make this an override
params = "<radius> <replace_node> [<pointing_dir:x|y|z|-x|-y|-z|?|front|back|left|right|up|down> ...]",
description = "Creates a dome shape with a specified radius of the defined node, optionally specifying the direction it should be pointing in (defaults to the positive y direction).",
privs = { worldedit = true },
require_pos = 1,
parse = function(params_text)
if not params_text then params_text = "" end
local parts = wea.split_shell(params_text)
if #parts < 2 then
return false, "Error: Not enough arguments (see /help /dome for usage information)."
end
local radius = tonumber(parts[1])
local replace_node = worldedit.normalize_nodename(parts[2])
if not radius then
return false, "Error: Invalid radius '"..parts[1].."'. The radius must be a positive integer."
end
if radius < 1 then
return false, "Error: The minimum radius size is 1, but you entered"..tostring(radius).."."
end
if not replace_node then
return false, "Error: Invalid replace_node '"..parts[1].."'."
end
local axes = wea.table.shallowcopy(parts)
table.remove(axes, 1)
table.remove(axes, 1)
if #axes == 0 then
table.insert(axes, "+y")
end
return true, radius, replace_node, axes
end,
nodes_needed = function(name, radius)
return 4/3 * math.pi * radius * radius * radius
end,
func = function(name, radius, replace_node, axes)
local start_time = wea.get_ms_time()
local success_a, pointing_dir = parse_stage2(name, axes)
if not success_a then return success_a, pointing_dir end
local pos = Vector3.clone(worldedit.pos1[name])
local success_b, nodes_replaced = wea.dome(
pos,
radius,
replace_node,
pointing_dir
)
if not success_b then return success_b, nodes_replaced end
local time_taken = wea.get_ms_time() - start_time
minetest.log("action", name.." used //dome+ at "..pos.." with a radius of "..tostring(radius)..", modifying "..nodes_replaced.." nodes in "..wea.format.human_time(time_taken))
return true, nodes_replaced.." nodes replaced "..wea.format.human_time(time_taken)
end
})

View file

@ -38,6 +38,7 @@ dofile(we_c.modpath.."/commands/walls.lua")
dofile(we_c.modpath.."/commands/spiral2.lua")
dofile(we_c.modpath.."/commands/copy.lua")
dofile(we_c.modpath.."/commands/move.lua")
dofile(we_c.modpath.."/commands/dome.lua")
dofile(we_c.modpath.."/commands/count.lua")
dofile(we_c.modpath.."/commands/sculpt.lua")