mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-12-22 19:45:02 +00:00
Fix a few small bugs
This commit is contained in:
parent
4b3833649c
commit
f3745dc6ba
5 changed files with 185 additions and 4 deletions
17
README.md
17
README.md
|
@ -50,6 +50,23 @@ Creates a hollow ellipsoid at position 1 with the radius `(rx, ry, rz)`. Works t
|
|||
//hollowellipsoid 21 11 41 stone
|
||||
```
|
||||
|
||||
### `//torus <major_radius > <minor_radius> <node_name>`
|
||||
Creates a solid torus at position 1 with the specified major and minor radii. The major radius is the distance from the centre of the torus to the centre of the circle bit, and the minor radius is the radius of the circle bit.
|
||||
|
||||
```
|
||||
//torus 10 5 15 ice
|
||||
//torus 3 5 10 dirt
|
||||
//torus 20 10 40 air
|
||||
```
|
||||
|
||||
### `//hollowtorus <rx> <ry> <rz> <node_name>`
|
||||
Creates a hollow torus at position 1 with the radius `(rx, ry, rz)`. Works the same way as `//torus` does.
|
||||
|
||||
```
|
||||
//hollowtorus 10 5 15 glass
|
||||
//hollowtorus 21 11 41 stone
|
||||
```
|
||||
|
||||
## Contributing
|
||||
Contributions are welcome! Please state in your pull request(s) that you release your contribution under the _Mozilla Public License 2.0_.
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@ function worldedit.ellipsoid(position, radius, target_node, hollow)
|
|||
local node_id_air = minetest.get_content_id("air")
|
||||
|
||||
local stride_z, stride_y = area.zstride, area.ystride
|
||||
-- TODO: This won't work, because we need to vary the calculation we use this in based on what part of the ellipsoid we're working on / in, not compare to a static value
|
||||
local radius_distance_sq = worldeditadditions.vector.lengthsquared(radius)
|
||||
|
||||
local count = 0 -- The number of nodes replaced
|
||||
|
||||
|
|
|
@ -11,3 +11,4 @@ dofile(minetest.get_modpath("worldeditadditions") .. "/utils.lua")
|
|||
dofile(minetest.get_modpath("worldeditadditions") .. "/floodfill.lua")
|
||||
dofile(minetest.get_modpath("worldeditadditions") .. "/overlay.lua")
|
||||
dofile(minetest.get_modpath("worldeditadditions") .. "/ellipsoid.lua")
|
||||
dofile(minetest.get_modpath("worldeditadditions") .. "/torus.lua")
|
||||
|
|
78
worldeditadditions/torus.lua
Normal file
78
worldeditadditions/torus.lua
Normal file
|
@ -0,0 +1,78 @@
|
|||
--- Overlap command. Places a specified node on top of
|
||||
-- @module worldeditadditions.overlay
|
||||
|
||||
function worldedit.torus(position, major_radius, minor_radius, target_node, hollow)
|
||||
-- position = { x, y, z }
|
||||
local total_radius = major_radius + minor_radius
|
||||
local inner_minor_radius = minor_radius - 1.75
|
||||
local major_radius_sq = major_radius*major_radius
|
||||
local minor_radius_sq = minor_radius*minor_radius
|
||||
local inner_minor_radius_sq = inner_minor_radius*inner_minor_radius
|
||||
|
||||
-- Fetch the nodes in the specified area
|
||||
-- OPTIMIZE: We should be able to calculate a more efficient box-area here
|
||||
local manip, area = worldedit.manip_helpers.init_radius(position, total_radius)
|
||||
local data = manip:get_data()
|
||||
|
||||
local node_id = minetest.get_content_id(target_node)
|
||||
local node_id_air = minetest.get_content_id("air")
|
||||
|
||||
local stride_z, stride_y = area.zstride, area.ystride
|
||||
|
||||
local count = 0 -- The number of nodes replaced
|
||||
|
||||
local idx_z_base = area:index(position.x - total_radius, position.y - total_radius, position.z - total_radius) -- initial z offset
|
||||
for z = -total_radius, total_radius do
|
||||
local z_sq = z*z
|
||||
|
||||
local idx_y_base = idx_z_base
|
||||
for y = -total_radius, total_radius do
|
||||
local y_sq = y*y
|
||||
|
||||
local i = idx_y_base
|
||||
for x = -total_radius, total_radius do
|
||||
local x_sq = x*x
|
||||
|
||||
-- (x^2+y^2+z^2-(a^2+b^2))^2-4 a b (b^2-z^2)
|
||||
-- Where:
|
||||
-- (x, y, z) is the point
|
||||
-- a is the major radius (centre to centre of circle)
|
||||
-- b is the minor radius (radius of circle
|
||||
local comp_a = (x_sq+y_sq+z_sq - (major_radius_sq+minor_radius_sq))
|
||||
local test_value = comp_a*comp_a - 4*major_radius*minor_radius*(minor_radius_sq-z_sq)
|
||||
|
||||
-- If we're inside the torus, then fill it in
|
||||
if test_value <= 1 then
|
||||
local place_ok = not hollow;
|
||||
|
||||
if not place_ok then
|
||||
-- It must be hollow! Do some additional calculations.
|
||||
local inner_comp_a = (x_sq+y_sq+z_sq - (major_radius_sq+inner_minor_radius_sq))
|
||||
local inner_test_value = inner_comp_a*inner_comp_a - 4*major_radius*inner_minor_radius*(inner_minor_radius_sq-z_sq)
|
||||
|
||||
-- It's only ok to place it if it's outside our inner torus
|
||||
place_ok = inner_test_value >= 0
|
||||
end
|
||||
|
||||
if place_ok then
|
||||
data[i] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
idx_y_base = idx_y_base + stride_y
|
||||
|
||||
end
|
||||
idx_z_base = idx_z_base + stride_z
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Save the modified nodes back to disk & return
|
||||
worldedit.manip_helpers.finish(manip, data)
|
||||
|
||||
return count
|
||||
end
|
|
@ -158,7 +158,7 @@ minetest.register_chatcommand("/ellipsoid", {
|
|||
-- TODO: This duplicates a lot of code. Perhaps we can trim it down a bit?
|
||||
minetest.register_chatcommand("/hollowellipsoid", {
|
||||
params = "<rx> <ry> <rz> <replace_node>",
|
||||
description = "Creates a 3D hollow ellipsoid with a radius of (rx, ry, rz) at pos1, filled with <replace_node>.",
|
||||
description = "Creates a 3D hollow ellipsoid with a radius of (rx, ry, rz) at pos1, made out of <replace_node>.",
|
||||
privs = { worldedit = true },
|
||||
func = safe_region(function(name, params_text)
|
||||
local target_node, radius = parse_params_ellipsoid(params_text)
|
||||
|
@ -181,10 +181,97 @@ minetest.register_chatcommand("/hollowellipsoid", {
|
|||
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.")
|
||||
worldedit.player_notify(name, "Error: Invalid input '" .. params_text .. "'. Try '/help /hollowellipsoid' to learn how to use this command.")
|
||||
return 0
|
||||
end
|
||||
|
||||
return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z)
|
||||
end)
|
||||
})
|
||||
|
||||
-- ████████ ██████ ██████ ██ ██ ███████
|
||||
-- ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██ ██ ██████ ██ ██ ███████
|
||||
-- ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██████ ██ ██ ██████ ███████
|
||||
local function parse_params_torus(params_text)
|
||||
local found, _, major_radius, minor_radius, replace_node = params_text:find("([0-9]+)%s+([0-9]+)%s+([a-z:_\\-]+)")
|
||||
|
||||
if found == nil then
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
major_radius = tonumber(major_radius)
|
||||
minor_radius = tonumber(minor_radius)
|
||||
|
||||
replace_node = worldedit.normalize_nodename(replace_node)
|
||||
|
||||
return replace_node, major_radius, minor_radius
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("/torus", {
|
||||
params = "<major_radius> <minor_radius> <replace_node>",
|
||||
description = "Creates a 3D torus with a major radius of <major_radius> and a minor radius of <minor_radius> at pos1, filled with <replace_node>.",
|
||||
privs = { worldedit = true },
|
||||
func = safe_region(function(name, params_text)
|
||||
local target_node, major_radius, minor_radius = parse_params_torus(params_text)
|
||||
|
||||
if not target_node then
|
||||
worldedit.player_notify(name, "Error: Invalid node name.")
|
||||
return false
|
||||
end
|
||||
if not major_radius or not minor_radius then
|
||||
worldedit.player_notify(name, "Error: Invalid radius(es).")
|
||||
return false
|
||||
end
|
||||
|
||||
local start_time = os.clock()
|
||||
local replaced = worldedit.torus(worldedit.pos1[name], major_radius, minor_radius, target_node, false)
|
||||
local time_taken = os.clock() - start_time
|
||||
|
||||
worldedit.player_notify(name, replaced .. " nodes replaced in " .. time_taken .. "s")
|
||||
minetest.log("action", name .. " used //torus at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. replaced .. " nodes in " .. time_taken .. "s")
|
||||
end, function(name, params_text)
|
||||
local target_node, major_radius, minor_radius = parse_params_torus(params_text)
|
||||
if not target_node or not major_radius or not minor_radius then
|
||||
worldedit.player_notify(name, "Error: Invalid input '" .. params_text .. "'. Try '/help /torus' to learn how to use this command.")
|
||||
return 0
|
||||
end
|
||||
|
||||
return math.ceil(2 * math.pi*math.pi * major_radius * minor_radius*minor_radius)
|
||||
end)
|
||||
})
|
||||
|
||||
-- TODO: This duplicates a lot of code. Perhaps we can trim it down a bit?
|
||||
minetest.register_chatcommand("/hollowtorus", {
|
||||
params = "<major_radius> <minor_radius> <replace_node>",
|
||||
description = "Creates a 3D hollow torus with a major radius of <major_radius> and a minor radius of <minor_radius> at pos1, made out of <replace_node>.",
|
||||
privs = { worldedit = true },
|
||||
func = safe_region(function(name, params_text)
|
||||
local target_node, major_radius, minor_radius = parse_params_torus(params_text)
|
||||
|
||||
if not target_node then
|
||||
worldedit.player_notify(name, "Error: Invalid node name.")
|
||||
return false
|
||||
end
|
||||
if not major_radius or not minor_radius then
|
||||
worldedit.player_notify(name, "Error: Invalid radius(es).")
|
||||
return false
|
||||
end
|
||||
|
||||
local start_time = os.clock()
|
||||
local replaced = worldedit.torus(worldedit.pos1[name], major_radius, minor_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 //hollowtorus at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. replaced .. " nodes in " .. time_taken .. "s")
|
||||
end, function(name, params_text)
|
||||
local target_node, major_radius, minor_radius = parse_params_torus(params_text)
|
||||
if not target_node or not major_radius or not minor_radius then
|
||||
worldedit.player_notify(name, "Error: Invalid input '" .. params_text .. "'. Try '/help /hollowtorus' to learn how to use this command.")
|
||||
return 0
|
||||
end
|
||||
|
||||
return math.ceil(2 * math.pi*math.pi * major_radius * minor_radius*minor_radius)
|
||||
end)
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue