Upgrade all main commands

This commit is contained in:
Starbeamrainbowlabs 2022-09-19 00:18:03 +01:00
parent a3acf3b16e
commit 41e3ebc7dd
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
22 changed files with 186 additions and 172 deletions

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- █████ ██ ██████
-- ██ ██ ██ ██ ██
-- ███████ ██ ██████
@ -17,17 +20,17 @@
-- @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.airapply(pos1, pos2, func)
local time_taken_all = worldeditadditions.get_ms_time()
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local time_taken_all = wea_c.get_ms_time()
pos1, pos2 = Vector3.sort(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_before:get_data()
local time_taken_fn = worldeditadditions.get_ms_time()
local time_taken_fn = wea_c.get_ms_time()
func()
time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn
time_taken_fn = wea_c.get_ms_time() - time_taken_fn
local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2)
local data_after = manip_after:get_data()
@ -37,7 +40,7 @@ function worldeditadditions.airapply(pos1, pos2, func)
for x = pos2.x, pos1.x, -1 do
local i_before = area_before:index(x, y, z)
local i_after = area_after:index(x, y, z)
local old_is_airlike = worldeditadditions.is_airlike(data_before[i_before])
local old_is_airlike = wea_c.is_airlike(data_before[i_before])
-- Roll everything that replaces nodes that aren't airlike
if not old_is_airlike then
@ -52,6 +55,6 @@ function worldeditadditions.airapply(pos1, pos2, func)
worldedit.manip_helpers.finish(manip_after, data_after)
time_taken_all = worldeditadditions.get_ms_time() - time_taken_all
time_taken_all = wea_c.get_ms_time() - time_taken_all
return true, { all = time_taken_all, fn = time_taken_fn }
end

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Bonemeal command.
-- Applies bonemeal to all notes
-- @module worldeditadditions.overlay
@ -6,7 +9,7 @@
-- chance Positive integer that represents the chance bonemealing will occur
function worldeditadditions.bonemeal(pos1, pos2, strength, chance, nodename_list)
if not nodename_list then nodename_list = {} end
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- This command requires the bonemeal mod to be installed
@ -15,7 +18,7 @@ function worldeditadditions.bonemeal(pos1, pos2, strength, chance, nodename_list
return false, "Bonemeal mod not loaded"
end
local node_list = worldeditadditions.table.map(nodename_list, function(nodename)
local node_list = wea_c.table.map(nodename_list, function(nodename)
return minetest.get_content_id(nodename)
end)
local node_list_count = #nodename_list
@ -34,9 +37,9 @@ function worldeditadditions.bonemeal(pos1, pos2, strength, chance, nodename_list
for x = pos2.x, pos1.x, -1 do
for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z)
if not worldeditadditions.is_airlike(data[i]) then
if not wea_c.is_airlike(data[i]) then
local should_bonemeal = true
if node_list_count > 0 and not worldeditadditions.table.contains(node_list, data[i]) then
if node_list_count > 0 and not wea_c.table.contains(node_list, data[i]) then
should_bonemeal = false
end
@ -45,7 +48,7 @@ function worldeditadditions.bonemeal(pos1, pos2, strength, chance, nodename_list
if should_bonemeal and math.random(0, chance - 1) == 0 then
bonemeal:on_use(
{ x = x, y = y, z = z },
Vector3.new(x, y, z),
strength,
nil
)

View File

@ -1,9 +1,9 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Copies a region to another location, potentially overwriting the exiting region.
-- @module worldeditadditions.copy
local wea = worldeditadditions
local Vector3 = wea.Vector3
-- ██████ ██████ ██████ ██ ██
-- ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ██ ██████ ████
@ -32,7 +32,7 @@ function worldeditadditions.copy(source_pos1, source_pos2, target_pos1, target_p
for x = source_pos2.x, source_pos1.x, -1 do
local source = Vector3.new(x, y, z)
local source_i = area_source:index(x, y, z)
local target = source:subtract(offset)
local target = source - offset
local target_i = area_target:index(target.x, target.y, target.z)
data_target[target_i] = data_source[source_i]

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Counts the nodes in a given area.
-- @module worldeditadditions.count
@ -7,7 +10,7 @@
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ██████ ██████ ██████ ██ ████ ██
function worldeditadditions.count(pos1, pos2, do_human_counts)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
@ -29,7 +32,7 @@ function worldeditadditions.count(pos1, pos2, do_human_counts)
for node_name, count in pairs(counts) do
table.insert(results, {
count,
tostring(worldeditadditions.round((count / total) * 100, 2)).."%",
tostring(wea_c.round((count / total) * 100, 2)).."%",
minetest.get_name_from_content_id(node_name)
})
end
@ -37,7 +40,7 @@ function worldeditadditions.count(pos1, pos2, do_human_counts)
if do_human_counts then
for key,item in pairs(results) do
item[1] = worldeditadditions.format.human_size(item[1], 2)
item[1] = wea_c.format.human_size(item[1], 2)
end
end

View File

@ -1,5 +1,5 @@
local wea = worldeditadditions
local Vector3 = wea.Vector3
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ██████ ██████ ███ ███ ███████
-- ██ ██ ██ ██ ████ ████ ██
@ -11,7 +11,7 @@ local Vector3 = wea.Vector3
-- @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.
-- @param pointing_dir Vector3 Optional. The direction the dome should point. Defaults to (0, 1, 0). See also wea.parse.axis_name.
-- @param pointing_dir Vector3 Optional. The direction the dome should point. Defaults to (0, 1, 0). See also wea_c.parse.axis_name.
-- @param hollow boolean Whether to make the dome hollow or not. Defaults to false.
function worldeditadditions.dome(pos, radius, replace_node, pointing_dir, hollow)
pos = Vector3.clone(pos)

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ███████ ██ ██ ██ ██████ ███████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██
-- █████ ██ ██ ██ ██████ ███████ █████
@ -13,12 +16,9 @@
-- @param hollow bool Whether the ellipsoid should be hollow or not.
-- @returns number The number of nodes filled to create the (optionally hollow) ellipsoid. This number will be lower with hollow ellipsoids, since the internals of an ellipsoid aren't altered.
function worldeditadditions.ellipsoid(position, radius, target_node, hollow)
radius = Vector3.clone(radius)
-- position = { x, y, z }
local hollow_inner_radius = {
x = radius.x - 1,
y = radius.y - 1,
z = radius.z - 1
}
local hollow_inner_radius = radius - 1
-- Fetch the nodes in the specified area
-- OPTIMIZE: We should be able to calculate a more efficient box-area here
@ -39,21 +39,19 @@ function worldeditadditions.ellipsoid(position, radius, target_node, hollow)
local i = idx_y_base
for x = -radius.x, radius.x do
local here = Vector3.new(x, y, z)
-- 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
local ellipsoid_dist = x_comp*x_comp + y_comp*y_comp + z_comp*z_comp
local comp = here / radius
local ellipsoid_dist = Vector3.dot(comp, comp)
if ellipsoid_dist <= 1 then
local place_ok = not hollow;
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
local h_comp = here / hollow_inner_radius
-- 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
place_ok = Vector3.dot(h_comp, h_comp) >= 1
end
if place_ok then

View File

@ -1,4 +1,5 @@
local wea = worldeditadditions
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ███████ ██ ██ ██ ██████ ███████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██
@ -8,21 +9,17 @@ local wea = worldeditadditions
function worldeditadditions.ellipsoid2(pos1, pos2, target_node, hollow)
pos1, pos2 = wea.Vector3.sort(pos1, pos2)
local volume = pos2:subtract(pos1)
local volume_half = volume:divide(2)
pos1, pos2 = Vector3.sort(pos1, pos2)
local volume = pos2 - pos1
local volume_half = volume / 2
local radius = pos2:subtract(pos1):divide(2)
local radius = (pos2 - pos1) / 2
print("DEBUG:ellipsoid2 | pos1: "..pos1..", pos2: "..pos2..", target_node: "..target_node)
print("DEBUG:ellipsoid2 radius", radius)
-- position = { x, y, z }
local hollow_inner_radius = {
x = radius.x - 1,
y = radius.y - 1,
z = radius.z - 1
}
local hollow_inner_radius = radius - 1
-- Fetch the nodes in the specified area
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
@ -35,26 +32,23 @@ function worldeditadditions.ellipsoid2(pos1, pos2, target_node, hollow)
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 pos_relative = wea.Vector3.new(x, y, z):subtract(pos1)
:subtract(volume_half)
local here = Vector3.new(x, y, z)
local pos_relative = (here - pos1) - volume_half
print("DEBUG pos1", pos1, "pos2", pos2, "volume_half", volume_half, "pos_relative", pos_relative)
-- If we're inside the ellipse, then fill it in
local comp = pos_relative:divide(radius)
local comp = pos_relative / radius
local ellipsoid_dist = comp:length_squared()
if ellipsoid_dist <= 1 then
local place_ok = not hollow;
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
local h_comp = here / hollow_inner_radius
-- 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
place_ok = Vector3.dot(h_comp, h_comp) >= 1
end
if place_ok then

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ███████ ██ ██ ██ ██████ ███████ ██████ ██ ██████
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- █████ ██ ██ ██ ██████ ███████ ██ ██ ██ ██ ██
@ -17,40 +20,29 @@
-- @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.ellipsoidapply(pos1, pos2, func)
local time_taken_all = worldeditadditions.get_ms_time()
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local time_taken_all = wea_c.get_ms_time()
pos1, pos2 = Vector3.sort(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_before:get_data()
local time_taken_fn = worldeditadditions.get_ms_time()
local time_taken_fn = wea_c.get_ms_time()
func()
time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn
time_taken_fn = wea_c.get_ms_time() - time_taken_fn
local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2)
local data_after = manip_after:get_data()
local radius = {
x = (pos2.x - pos1.x) / 2,
y = (pos2.y - pos1.y) / 2,
z = (pos2.z - pos1.z) / 2
}
local e_centre = {
x = pos2.x - radius.x,
y = pos2.y - radius.y,
z = pos2.z - radius.z
}
local radius = (pos2 - pos1) / 2
local e_centre = pos2 - radius
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 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
local distance_mult = x_comp*x_comp + y_comp*y_comp + z_comp*z_comp
local comp = (Vector3.new(x, y, z) - e_centre) / radius
local distance_mult = Vector3.dot(comp, comp)
-- Roll everything that's outside the ellipse back
if distance_mult > 1 then
@ -65,6 +57,6 @@ function worldeditadditions.ellipsoidapply(pos1, pos2, func)
worldedit.manip_helpers.finish(manip_after, data_after)
time_taken_all = worldeditadditions.get_ms_time() - time_taken_all
time_taken_all = wea_c.get_ms_time() - time_taken_all
return true, { all = time_taken_all, fn = time_taken_fn }
end

View File

@ -1,8 +1,11 @@
--- Overlap command. Places a specified node on top of each column.
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Fill caves command. Fills underneath non-air nodes in the defined region.
-- @module worldeditadditions.overlay
function worldeditadditions.fillcaves(pos1, pos2, node_name)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
@ -12,8 +15,8 @@ function worldeditadditions.fillcaves(pos1, pos2, node_name)
local node_id_replace = minetest.get_content_id(node_name)
local node_id_ignore = minetest.get_content_id("ignore")
-- minetest.log("action", "pos1: " .. worldeditadditions.vector.tostring(pos1))
-- minetest.log("action", "pos2: " .. worldeditadditions.vector.tostring(pos2))
-- minetest.log("action", "pos1: " .. pos1)
-- minetest.log("action", "pos2: " .. pos2)
-- z y x is the preferred loop order, but that isn't really possible here
@ -27,7 +30,7 @@ function worldeditadditions.fillcaves(pos1, pos2, node_name)
for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z)
local is_air = worldeditadditions.is_airlike(data[i]) or worldeditadditions.is_liquidlike(data[i])
local is_air = wea_c.is_airlike(data[i]) or wea_c.is_liquidlike(data[i])
local is_ignore = data[i] == node_id_ignore
-- If the previous node was air and this one isn't, then we've found the top level

View File

@ -1,13 +1,18 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Flood-fill command for complex lakes etc.
-- @module worldeditadditions.floodfill
local wea = worldeditadditions
function worldeditadditions.floodfill(start_pos, radius, replace_node)
start_pos = Vector3.clone(start_pos)
-- Calculate the area we want to modify
local pos1 = vector.add(start_pos, { x = radius, y = 0, z = radius })
local pos2 = vector.subtract(start_pos, { x = radius, y = radius, z = radius })
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local pos1 = start_pos + Vector3.new(radius, 0, radius)
local pos2 = start_pos - Vector3.new(radius, radius, radius)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
@ -27,7 +32,7 @@ function worldeditadditions.floodfill(start_pos, radius, replace_node)
end
local count = 0
local remaining_nodes = wea.Queue.new() remaining_nodes:enqueue(start_pos_index)
local remaining_nodes = wea_c.Queue.new() remaining_nodes:enqueue(start_pos_index)
-- Do the floodfill
while remaining_nodes:is_empty() == false do
@ -41,35 +46,35 @@ function worldeditadditions.floodfill(start_pos, radius, replace_node)
-- We don't need to go upwards here, since we're filling in lake-style
local xplus = cur + 1 -- +X
if data[xplus] == search_id and
worldeditadditions.vector.lengthsquared(vector.subtract(area:position(xplus), start_pos)) < radius_sq and
(Vector3.clone(area:position(xplus)) - start_pos):length_squared() < radius_sq and
not remaining_nodes:contains(xplus) then
-- minetest.log("action", "[floodfill] [+X] index " .. xplus .. " is a " .. data[xplus] .. ", searching for a " .. search_id)
remaining_nodes:enqueue(xplus)
end
local xminus = cur - 1 -- -X
if data[xminus] == search_id and
worldeditadditions.vector.lengthsquared(vector.subtract(area:position(xminus), start_pos)) < radius_sq and
(Vector3.new(area:position(xminus)) - start_pos):length_squared() < radius_sq and
not remaining_nodes:contains(xminus) then
-- minetest.log("action", "[floodfill] [-X] index " .. xminus .. " is a " .. data[xminus] .. ", searching for a " .. search_id)
remaining_nodes:enqueue(xminus)
end
local zplus = cur + area.zstride -- +Z
if data[zplus] == search_id and
worldeditadditions.vector.lengthsquared(vector.subtract(area:position(zplus), start_pos)) < radius_sq and
(Vector3.new(area:position(zplus)) - start_pos):length_squared() < radius_sq and
not remaining_nodes:contains(zplus) then
-- minetest.log("action", "[floodfill] [+Z] index " .. zplus .. " is a " .. data[zplus] .. ", searching for a " .. search_id)
remaining_nodes:enqueue(zplus)
end
local zminus = cur - area.zstride -- -Z
if data[zminus] == search_id and
worldeditadditions.vector.lengthsquared(vector.subtract(area:position(zminus), start_pos)) < radius_sq and
(Vector3.new(area:position(zminus)) - start_pos):length_squared() < radius_sq and
not remaining_nodes:contains(zminus) then
-- minetest.log("action", "[floodfill] [-Z] index " .. zminus .. " is a " .. data[zminus] .. ", searching for a " .. search_id)
remaining_nodes:enqueue(zminus)
end
local yminus = cur - area.ystride -- -Y
if data[yminus] == search_id and
worldeditadditions.vector.lengthsquared(vector.subtract(area:position(yminus), start_pos)) < radius_sq and
(Vector3.new(area:position(yminus)) - start_pos):length_squared() < radius_sq and
not remaining_nodes:contains(yminus) then
-- minetest.log("action", "[floodfill] [-Y] index " .. yminus .. " is a " .. data[yminus] .. ", searching for a " .. search_id)
remaining_nodes:enqueue(yminus)

View File

@ -1,9 +1,12 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Overlap command. Places a specified node on top of each column.
-- @module worldeditadditions.layers
function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weights)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
local weight_total = 0
for _name,weight in pairs(sapling_weights) do
@ -33,7 +36,7 @@ function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weigh
local i = area:index(x, y, z)
local node_id = data[i]
if not group_cache[node_id] then
group_cache[node_id] = worldeditadditions.is_sapling(node_id)
group_cache[node_id] = wea_c.is_sapling(node_id)
end
if group_cache[node_id] then
@ -50,7 +53,7 @@ function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weigh
new_name_at_pos = minetest.get_node({ z = z, y = y, x = x }).name
new_id_at_pos = minetest.get_content_id(new_name_at_pos)
if not group_cache[new_id_at_pos] then
group_cache[new_id_at_pos] = worldeditadditions.is_sapling(new_id_at_pos)
group_cache[new_id_at_pos] = wea_c.is_sapling(new_id_at_pos)
end
if not group_cache[new_id_at_pos] then
did_grow = true
@ -84,7 +87,7 @@ function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weigh
for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z)
if not group_cache[data[i]] then
group_cache[data[i]] = worldeditadditions.is_sapling(data[i])
group_cache[data[i]] = wea_c.is_sapling(data[i])
end
if group_cache[data[i]] then
@ -95,7 +98,7 @@ function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weigh
end
stats.successes = #stats.attempts
stats.attempts_avg = worldeditadditions.average(stats.attempts)
stats.attempts_avg = wea_c.average(stats.attempts)
-- Save the modified nodes back to disk & return
worldedit.manip_helpers.finish(manip, data)

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ██ ██ ██████ ██ ██ ██████ ██ ██
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ███████ ██ ██ ██ ██ ██ ██ ██ █ ██
@ -8,7 +11,7 @@
-- (think of the bits of the outermost parts of the defined region as the
-- 'walls' to a box)
function worldeditadditions.hollow(pos1, pos2, wall_thickness)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
@ -18,8 +21,8 @@ function worldeditadditions.hollow(pos1, pos2, wall_thickness)
local node_id_ignore = minetest.get_content_id("ignore")
local node_id_air = minetest.get_content_id("air")
-- minetest.log("action", "pos1: " .. worldeditadditions.vector.tostring(pos1))
-- minetest.log("action", "pos2: " .. worldeditadditions.vector.tostring(pos2))
-- minetest.log("action", "pos1: " ..pos1)
-- minetest.log("action", "pos2: " .. pos2)
local changes = { replaced = 0 }
for z = pos2.z - wall_thickness, pos1.z + wall_thickness, -1 do
@ -27,7 +30,7 @@ function worldeditadditions.hollow(pos1, pos2, wall_thickness)
for x = pos2.x - wall_thickness, pos1.x + wall_thickness, -1 do
local i = area:index(x, y, z)
local is_air = worldeditadditions.is_airlike(data[i])
local is_air = wea_c.is_airlike(data[i])
local is_ignore = data[i] == node_id_ignore
if not is_ignore and not is_air then

View File

@ -1,18 +1,20 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ██ █████ ██ ██ ███████ ██████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ██ ███████ ████ █████ ██████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██
-- ███████ ██ ██ ██ ███████ ██ ██ ███████
local wea = worldeditadditions
local function print_slopes(slopemap, width)
local copy = wea.table.shallowcopy(slopemap)
local copy = wea_c.table.shallowcopy(slopemap)
for key,value in pairs(copy) do
copy[key] = wea.round(math.deg(value), 2)
copy[key] = wea_c.round(math.deg(value), 2)
end
worldeditadditions.format.array_2d(copy, width)
wea_c.format.array_2d(copy, width)
end
--- Replaces the non-air nodes in each column with a list of nodes from top to bottom.
@ -22,7 +24,7 @@ end
-- @param min_slope number?
-- @param max_slope number?
function worldeditadditions.layers(pos1, pos2, node_weights, min_slope, max_slope)
pos1, pos2 = wea.Vector3.sort(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
if not min_slope then min_slope = math.rad(0) end
if not max_slope then max_slope = math.rad(180) end
-- pos2 will always have the highest co-ordinates now
@ -33,13 +35,13 @@ function worldeditadditions.layers(pos1, pos2, node_weights, min_slope, max_slop
local node_id_ignore = minetest.get_content_id("ignore")
local node_ids, node_ids_count = wea.unwind_node_list(node_weights)
local node_ids, node_ids_count = wea_c.unwind_node_list(node_weights)
local heightmap, heightmap_size = wea.terrain.make_heightmap(
local heightmap, heightmap_size = wea_c.terrain.make_heightmap(
pos1, pos2,
manip, area, data
)
local slopemap = wea.terrain.calculate_slopes(heightmap, heightmap_size)
local slopemap = wea_c.terrain.calculate_slopes(heightmap, heightmap_size)
-- worldeditadditions.format.array_2d(heightmap, heightmap_size.x)
-- print_slopes(slopemap, heightmap_size.x)
--luacheck:ignore 311
@ -68,7 +70,7 @@ function worldeditadditions.layers(pos1, pos2, node_weights, min_slope, max_slop
for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z)
local is_air = wea.is_airlike(data[i])
local is_air = wea_c.is_airlike(data[i])
local is_ignore = data[i] == node_id_ignore
if not is_air and not is_ignore then

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_commands
local Vector3 = wea_c.Vector3
--- Counts the nodes in a given area.
-- @module worldeditadditions.count
@ -9,11 +12,11 @@
function worldeditadditions.line(pos1, pos2, thickness, node_name)
local pos1_sorted, pos2_sorted = worldedit.sort_pos(pos1, pos2)
local pos1_sorted, pos2_sorted = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
pos1 = vector.new(pos1)
pos2 = vector.new(pos2)
pos1 = Vector3.clone(pos1)
pos2 = Vector3.clone(pos2)
local node_id_replace = minetest.get_content_id(node_name)
@ -26,16 +29,11 @@ function worldeditadditions.line(pos1, pos2, thickness, node_name)
for z = pos2_sorted.z, pos1_sorted.z, -1 do
for x = pos2_sorted.x, pos1_sorted.x, -1 do
for y = pos2_sorted.y, pos1_sorted.y, -1 do
local here = vector.new(x, y, z)
local D = vector.normalize(
vector.subtract(pos2, pos1)
)
local d = vector.dot(vector.subtract(here, pos1), D)
local closest_on_line = vector.add(
pos1,
vector.multiply(D, d)
)
local distance = vector.length(vector.subtract(here, closest_on_line))
local here = Vector3.new(x, y, z)
local D = (pos2 - pos1):normalise()
local d = Vector3.dot(here - pos1, D)
local closest_on_line = pos1 + (D * d)
local distance = (here - closest_on_line):length()
if distance < thickness then
data[area:index(x, y, z)] = node_id_replace

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_commands
local Vector3 = wea_c.Vector3
--- Generates a maze.
-- Algorithm origin: https://starbeamrainbowlabs.com/blog/article.php?article=posts/070-Language-Review-Lua.html
-- @module worldeditadditions.maze
@ -117,16 +120,17 @@ end
-- local world = maze(os.time(), width, height)
function worldeditadditions.maze2d(pos1, pos2, target_node, seed, path_length, path_width)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- getExtent() returns the number of nodes in the VoxelArea, which might be larger than we actually asked for
local extent = {
x = (pos2.x - pos1.x) + 1, path_length, path_width,
y = (pos2.y - pos1.y) + 1, -- not a dimension passed to the maze generator itself
z = (pos2.z - pos1.z) + 1, path_length, path_width
}
-- minetest.log("action", "extent: ("..extent.x..", "..extent.y..", "..extent.z..")")
local extent = (pos2 - pos1) + 1
--- Extent:
-- x = path_length, path_width
-- y = not a dimension passed to the maze generator itself
-- z = path_length, path_width
-- minetest.log("action", "extent: "..extent)
if extent.x < 3 or extent.y < 1 or extent.z < 3 then
minetest.log("error", "[worldeditadditions/maze] error: either x, y of the extent were less than 3, or z of the extent was less than 1")

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_commands
local Vector3 = wea_c.Vector3
--- Generates a maze.
-- Algorithm origin: https://starbeamrainbowlabs.com/blog/article.php?article=posts/070-Language-Review-Lua.html
-- @module worldeditadditions.maze
@ -169,15 +172,12 @@ end
-- local world = maze(os.time(), width, height)
function worldeditadditions.maze3d(pos1, pos2, target_node, seed, path_length, path_width, path_depth)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- getExtent() returns the number of nodes in the VoxelArea, which might be larger than we actually asked for
local extent = {
x = (pos2.x - pos1.x) + 1,
y = (pos2.y - pos1.y) + 1,
z = (pos2.z - pos1.z) + 1
}
local extent = (pos2 - pos1) + 1
-- minetest.log("action", "extent: ("..extent.x..", "..extent.y..", "..extent.z..")")
if extent.x < 3 or extent.y < 3 or extent.z < 3 then

View File

@ -1,8 +1,8 @@
--- Copies a region to another location, potentially overwriting the exiting region.
-- @module worldeditadditions.copy
local wea = worldeditadditions
local Vector3 = wea.Vector3
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ███ ███ ██████ ██ ██ ███████
-- ████ ████ ██ ██ ██ ██ ██

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_commands
local Vector3 = wea_c.Vector3
-- ███ ██ ██████ ██ ███████ ███████ █████ ██████ ██████ ██ ██ ██ ██████ ██████
-- ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ██ ██ ██ ██ ███████ █████ ███████ ██████ ██████ ██ ████ █████ ██ ██
@ -11,8 +14,8 @@
-- @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.noiseapply2d(pos1, pos2, threshold, scale, func)
local time_taken_all = worldeditadditions.get_ms_time()
pos1, pos2 = worldeditadditions.Vector3.sort(pos1, pos2)
local time_taken_all = wea_c.get_ms_time()
pos1, pos2 = Vector3.sort(pos1, pos2)
if not threshold then threshold = 0.5 end
-- pos2 will always have the highest co-ordinates now
@ -20,14 +23,14 @@ function worldeditadditions.noiseapply2d(pos1, pos2, threshold, scale, func)
local manip_before, area_before = worldedit.manip_helpers.init(pos1, pos2)
local data_before = manip_before:get_data()
local time_taken_fn = worldeditadditions.get_ms_time()
local time_taken_fn = wea_c.get_ms_time()
func()
time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn
time_taken_fn = wea_c.get_ms_time() - time_taken_fn
local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2)
local data_after = manip_after:get_data()
local size2d = pos2 - pos1 + worldeditadditions.Vector3.new(1, 1, 1)
local size2d = pos2 - pos1 + Vector3.new(1, 1, 1)
print("DEBUG pos1", pos1, "pos2", pos2, "size2d", size2d)
local success, noise = worldeditadditions.noise.make_2d(size2d, pos1, {
algorithm = "perlinmt",
@ -55,6 +58,6 @@ function worldeditadditions.noiseapply2d(pos1, pos2, threshold, scale, 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
time_taken_all = wea_c.get_ms_time() - time_taken_all
return true, { all = time_taken_all, fn = time_taken_fn }
end

View File

@ -1,8 +1,11 @@
local wea_c = worldeditadditions_commands
local Vector3 = wea_c.Vector3
--- Overlap command. Places a specified node on top of each column.
-- @module worldeditadditions.overlay
function worldeditadditions.overlay(pos1, pos2, node_weights)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
@ -11,7 +14,7 @@ function worldeditadditions.overlay(pos1, pos2, node_weights)
local node_id_ignore = minetest.get_content_id("ignore")
local node_ids, node_ids_count = worldeditadditions.make_weighted(node_weights)
local node_ids, node_ids_count = wea_c.make_weighted(node_weights)
-- minetest.log("action", "pos1: " .. worldeditadditions.vector.tostring(pos1))
-- minetest.log("action", "pos2: " .. worldeditadditions.vector.tostring(pos2))
@ -26,11 +29,11 @@ function worldeditadditions.overlay(pos1, pos2, node_weights)
-- print("\n\n[overlay] ****** column start ******")
for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z)
-- print("[overlay] pos", x, y, z, "id", data[i], "name", minetest.get_name_from_content_id(data[i]), "is_liquid", worldeditadditions.is_liquidlike(data[i]))
-- print("[overlay] pos", x, y, z, "id", data[i], "name", minetest.get_name_from_content_id(data[i]), "is_liquid", wea_c.is_liquidlike(data[i]))
local is_air = worldeditadditions.is_airlike(data[i])
local is_liquid = worldeditadditions.is_liquidlike(data[i])
-- wielded_light is now handled by worldeditadditions.is_airlike
local is_air = wea_c.is_airlike(data[i])
local is_liquid = wea_c.is_liquidlike(data[i])
-- wielded_light is now handled by wea_c.is_airlike
local is_ignore = data[i] == node_id_ignore

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_commands
local Vector3 = wea_c.Vector3
--- Like //mix, but replaces a given node instead.
-- @module worldeditadditions.replacemix
@ -7,7 +10,7 @@
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ███████ ██ ███████ ██ ██ ██████ ███████ ██ ██ ██ ██ ██
function worldeditadditions.replacemix(pos1, pos2, target_node, target_node_chance, replacements)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
@ -22,7 +25,7 @@ function worldeditadditions.replacemix(pos1, pos2, target_node, target_node_chan
local distribution = {}
-- Generate the list of node ids
local node_ids_replace, node_ids_replace_count = worldeditadditions.make_weighted(replacements)
local node_ids_replace, node_ids_replace_count = wea_c.make_weighted(replacements)
for node_name, weight in pairs(replacements) do
distribution[minetest.get_content_id(node_name)] = 0
end

View File

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ███████ ██████ █████ ██ ███████ ██████ ██████ ██ ██ ███ ██
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
-- ███████ ██ ███████ ██ █████ ██ ██ ██ ██ ██ █ ██ ██ ██ ██
@ -11,7 +14,9 @@
-- @param anchor Vector The direction to scale in - as a vector. e.g. { x = -1, y = 1, z = -1 } would mean scale in the negative x, positive y, and nevative z directions.
-- @return boolean, string|table Whether the operation was successful or not. If not, then an error messagea as a string is also passed. If it was, then a statistics object is returned instead.
function worldeditadditions.scale_down(pos1, pos2, scale, anchor)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
pos1, pos2 = Vector3.sort(pos1, pos2)
scale = Vector3.clone(scale)
if scale.x > 1 or scale.y > 1 or scale.z > 1 or scale.x < -1 or scale.y < -1 or scale.z < -1 then
return false, "Error: Scale factor vectors may not mix values -1 < factor < 1 and (1 < factor or factor < -1) - in other words, you can't scale both up and down at the same time (try worldeditadditions.scale, which automatically applies such scale factor vectors as 2 successive operations)"
end
@ -19,31 +24,23 @@ function worldeditadditions.scale_down(pos1, pos2, scale, anchor)
return false, "Error: One of the components of the anchor vector was 0 (anchor components should either be greater than or less than 0 to indicate the anchor to scale in.)"
end
local scale_down = {
x = math.floor(1 / scale.x),
y = math.floor(1 / scale.y),
z = math.floor(1 / scale.z)
}
local size = vector.subtract(pos2, pos1)
local scale_down = (1 / scale):floor()
local size = pos2 - pos1
if size.x < scale_down.x or size.y < scale_down.y or size.z < scale.z then
return false, "Error: Area isn't big enough to apply scale down by "..worldeditadditions.vector.tostring(scale).."."
return false, "Error: Area isn't big enough to apply scale down by "..scale.."."
end
local size_small = {
x = math.floor(size.x / scale_down.x),
y = math.floor(size.y / scale_down.y),
z = math.floor(size.z / scale_down.z)
}
local size_small = (size / scale_down):floor()
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
local data = manip:get_data()
local data_copy = worldeditadditions.table.shallowcopy(data)
local data_copy = wea_c.table.shallowcopy(data)
local node_id_air = minetest.get_content_id("air")
local pos1_small = vector.new(pos1)
local pos2_small = vector.new(pos2)
local pos1_small = pos1:clone()
local pos2_small = pos2:clone()
if anchor.x < 1 then pos1_small.x = pos2_small.x - size_small.x
else pos2_small.x = pos1_small.x + size_small.x end
@ -65,22 +62,18 @@ function worldeditadditions.scale_down(pos1, pos2, scale, anchor)
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 posi_rel = vector.subtract({ x = x, y = y, z = z }, pos1)
local posi_rel = Vector3.new(x, y, z) - pos1
-- local posi_copy = worldeditadditions.table.shallowcopy(posi_rel)
-- local posi_copy = wea_c.table.shallowcopy(posi_rel)
-- posi_copy = vector.floor(vector.divide(posi_rel/*, scale_down*/))
local posi_copy = {
x = math.floor(posi_rel.x / scale_down.x),
y = math.floor(posi_rel.y / scale_down.y),
z = math.floor(posi_rel.z / scale_down.z)
}
local posi_copy = posi_rel / scale_down
if anchor.x < 0 then posi_copy.x = size.x - posi_copy.x end
if anchor.y < 0 then posi_copy.y = size.y - posi_copy.y end
if anchor.z < 0 then posi_copy.z = size.z - posi_copy.z end
posi_copy = vector.add(pos1, posi_copy)
posi_copy = pos1 + posi_copy
local i_source = area:index(x, y, z)
local i_target = area:index(posi_copy.x, posi_copy.y, posi_copy.z)

View File

@ -95,7 +95,8 @@ function Vector3.mul(a, b) return Vector3.multiply(a, b) end
-- @returns Vector3 The result as a new Vector3 object.
function Vector3.divide(a, b)
if type(a) == "number" then
return Vector3.new(b.x / a, b.y / a, b.z / a)
return Vector3.new(a / b.x, a/ b.y, a / b.z)
-- return Vector3.new(b.x / a, b.y / a, b.z / a) -- BUG: is this a bug?
elseif type(b) == "number" then
return Vector3.new(a.x / b, a.y / b, a.z / b)
end