Upgrade all main commands

This commit is contained in:
Starbeamrainbowlabs 2022-09-19 00:18:03 +01:00
parent a3acf3b16e
commit 41e3ebc7dd
No known key found for this signature in database
GPG Key ID: 1BE5172E637709C2
22 changed files with 186 additions and 172 deletions

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

@ -1,3 +1,6 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
--- Bonemeal command. --- Bonemeal command.
-- Applies bonemeal to all notes -- Applies bonemeal to all notes
-- @module worldeditadditions.overlay -- @module worldeditadditions.overlay
@ -6,7 +9,7 @@
-- chance Positive integer that represents the chance bonemealing will occur -- chance Positive integer that represents the chance bonemealing will occur
function worldeditadditions.bonemeal(pos1, pos2, strength, chance, nodename_list) function worldeditadditions.bonemeal(pos1, pos2, strength, chance, nodename_list)
if not nodename_list then nodename_list = {} end 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 -- pos2 will always have the highest co-ordinates now
-- This command requires the bonemeal mod to be installed -- 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" return false, "Bonemeal mod not loaded"
end 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) return minetest.get_content_id(nodename)
end) end)
local node_list_count = #nodename_list 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 x = pos2.x, pos1.x, -1 do
for y = pos2.y, pos1.y, -1 do for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z) 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 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 should_bonemeal = false
end 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 if should_bonemeal and math.random(0, chance - 1) == 0 then
bonemeal:on_use( bonemeal:on_use(
{ x = x, y = y, z = z }, Vector3.new(x, y, z),
strength, strength,
nil nil
) )

@ -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. --- Copies a region to another location, potentially overwriting the exiting region.
-- @module worldeditadditions.copy -- @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 for x = source_pos2.x, source_pos1.x, -1 do
local source = Vector3.new(x, y, z) local source = Vector3.new(x, y, z)
local source_i = area_source:index(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) local target_i = area_target:index(target.x, target.y, target.z)
data_target[target_i] = data_source[source_i] data_target[target_i] = data_source[source_i]

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

@ -1,5 +1,5 @@
local wea = worldeditadditions local wea_c = worldeditadditions_core
local Vector3 = wea.Vector3 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 pos Vector3 The central point to start drawing the dome from.
-- @param radius number The radius of the dome to create. -- @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 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. -- @param hollow boolean Whether to make the dome hollow or not. Defaults to false.
function worldeditadditions.dome(pos, radius, replace_node, pointing_dir, hollow) function worldeditadditions.dome(pos, radius, replace_node, pointing_dir, hollow)
pos = Vector3.clone(pos) pos = Vector3.clone(pos)

@ -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. -- @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. -- @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) function worldeditadditions.ellipsoid(position, radius, target_node, hollow)
radius = Vector3.clone(radius)
-- position = { x, y, z } -- position = { x, y, z }
local hollow_inner_radius = { local hollow_inner_radius = radius - 1
x = radius.x - 1,
y = radius.y - 1,
z = radius.z - 1
}
-- Fetch the nodes in the specified area -- Fetch the nodes in the specified area
-- OPTIMIZE: We should be able to calculate a more efficient box-area here -- 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 local i = idx_y_base
for x = -radius.x, radius.x do for x = -radius.x, radius.x do
local here = Vector3.new(x, y, z)
-- If we're inside the ellipse, then fill it in -- 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 comp = here / radius
local ellipsoid_dist = x_comp*x_comp + y_comp*y_comp + z_comp*z_comp
local ellipsoid_dist = Vector3.dot(comp, comp)
if ellipsoid_dist <= 1 then if ellipsoid_dist <= 1 then
local place_ok = not hollow; local place_ok = not hollow;
if not place_ok then if not place_ok then
-- It must be hollow! Do some additional calculations. -- It must be hollow! Do some additional calculations.
local hx_comp = x/hollow_inner_radius.x local h_comp = here / hollow_inner_radius
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 -- 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 end
if place_ok then if place_ok then

@ -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) function worldeditadditions.ellipsoid2(pos1, pos2, target_node, hollow)
pos1, pos2 = wea.Vector3.sort(pos1, pos2) pos1, pos2 = Vector3.sort(pos1, pos2)
local volume = pos2:subtract(pos1) local volume = pos2 - pos1
local volume_half = volume:divide(2) 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 | pos1: "..pos1..", pos2: "..pos2..", target_node: "..target_node)
print("DEBUG:ellipsoid2 radius", radius) print("DEBUG:ellipsoid2 radius", radius)
-- position = { x, y, z } -- position = { x, y, z }
local hollow_inner_radius = { local hollow_inner_radius = radius - 1
x = radius.x - 1,
y = radius.y - 1,
z = radius.z - 1
}
-- Fetch the nodes in the specified area -- Fetch the nodes in the specified area
local manip, area = worldedit.manip_helpers.init(pos1, pos2) 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 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 here = Vector3.new(x, y, z)
local pos_relative = wea.Vector3.new(x, y, z):subtract(pos1) local pos_relative = (here - pos1) - volume_half
:subtract(volume_half)
print("DEBUG pos1", pos1, "pos2", pos2, "volume_half", volume_half, "pos_relative", pos_relative) print("DEBUG pos1", pos1, "pos2", pos2, "volume_half", volume_half, "pos_relative", pos_relative)
-- If we're inside the ellipse, then fill it in -- 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() local ellipsoid_dist = comp:length_squared()
if ellipsoid_dist <= 1 then if ellipsoid_dist <= 1 then
local place_ok = not hollow; local place_ok = not hollow;
if not place_ok then if not place_ok then
-- It must be hollow! Do some additional calculations. -- It must be hollow! Do some additional calculations.
local hx_comp = x/hollow_inner_radius.x local h_comp = here / hollow_inner_radius
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 -- 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 end
if place_ok then if place_ok then

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

@ -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 -- @module worldeditadditions.overlay
function worldeditadditions.fillcaves(pos1, pos2, node_name) 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 -- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area -- 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_replace = minetest.get_content_id(node_name)
local node_id_ignore = minetest.get_content_id("ignore") local node_id_ignore = minetest.get_content_id("ignore")
-- minetest.log("action", "pos1: " .. worldeditadditions.vector.tostring(pos1)) -- minetest.log("action", "pos1: " .. pos1)
-- minetest.log("action", "pos2: " .. worldeditadditions.vector.tostring(pos2)) -- minetest.log("action", "pos2: " .. pos2)
-- z y x is the preferred loop order, but that isn't really possible here -- 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 for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z) 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 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 -- If the previous node was air and this one isn't, then we've found the top level

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

@ -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. --- Overlap command. Places a specified node on top of each column.
-- @module worldeditadditions.layers -- @module worldeditadditions.layers
function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weights) 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 local weight_total = 0
for _name,weight in pairs(sapling_weights) do 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 i = area:index(x, y, z)
local node_id = data[i] local node_id = data[i]
if not group_cache[node_id] then 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 end
if group_cache[node_id] then 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_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) new_id_at_pos = minetest.get_content_id(new_name_at_pos)
if not group_cache[new_id_at_pos] then 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 end
if not group_cache[new_id_at_pos] then if not group_cache[new_id_at_pos] then
did_grow = true did_grow = true
@ -84,7 +87,7 @@ function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weigh
for y = pos2.y, pos1.y, -1 do for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z) local i = area:index(x, y, z)
if not group_cache[data[i]] then 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 end
if group_cache[data[i]] then if group_cache[data[i]] then
@ -95,7 +98,7 @@ function worldeditadditions.forest(pos1, pos2, density_multiplier, sapling_weigh
end end
stats.successes = #stats.attempts 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 -- Save the modified nodes back to disk & return
worldedit.manip_helpers.finish(manip, data) worldedit.manip_helpers.finish(manip, data)

@ -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 -- (think of the bits of the outermost parts of the defined region as the
-- 'walls' to a box) -- 'walls' to a box)
function worldeditadditions.hollow(pos1, pos2, wall_thickness) 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 -- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area -- 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_ignore = minetest.get_content_id("ignore")
local node_id_air = minetest.get_content_id("air") local node_id_air = minetest.get_content_id("air")
-- minetest.log("action", "pos1: " .. worldeditadditions.vector.tostring(pos1)) -- minetest.log("action", "pos1: " ..pos1)
-- minetest.log("action", "pos2: " .. worldeditadditions.vector.tostring(pos2)) -- minetest.log("action", "pos2: " .. pos2)
local changes = { replaced = 0 } local changes = { replaced = 0 }
for z = pos2.z - wall_thickness, pos1.z + wall_thickness, -1 do 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 for x = pos2.x - wall_thickness, pos1.x + wall_thickness, -1 do
local i = area:index(x, y, z) 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 local is_ignore = data[i] == node_id_ignore
if not is_ignore and not is_air then if not is_ignore and not is_air then

@ -1,18 +1,20 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
-- ██ █████ ██ ██ ███████ ██████ ███████ -- ██ █████ ██ ██ ███████ ██████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ██ ███████ ████ █████ ██████ ███████ -- ██ ███████ ████ █████ ██████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██ ██ ██ ██ ██ ██
-- ███████ ██ ██ ██ ███████ ██ ██ ███████ -- ███████ ██ ██ ██ ███████ ██ ██ ███████
local wea = worldeditadditions
local function print_slopes(slopemap, width) 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 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 end
worldeditadditions.format.array_2d(copy, width) wea_c.format.array_2d(copy, width)
end end
--- Replaces the non-air nodes in each column with a list of nodes from top to bottom. --- 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 min_slope number?
-- @param max_slope number? -- @param max_slope number?
function worldeditadditions.layers(pos1, pos2, node_weights, min_slope, max_slope) 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 min_slope then min_slope = math.rad(0) end
if not max_slope then max_slope = math.rad(180) end if not max_slope then max_slope = math.rad(180) end
-- pos2 will always have the highest co-ordinates now -- 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_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, pos1, pos2,
manip, area, data 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) -- worldeditadditions.format.array_2d(heightmap, heightmap_size.x)
-- print_slopes(slopemap, heightmap_size.x) -- print_slopes(slopemap, heightmap_size.x)
--luacheck:ignore 311 --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 for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z) 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 local is_ignore = data[i] == node_id_ignore
if not is_air and not is_ignore then if not is_air and not is_ignore then

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

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

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

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

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

@ -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. --- Overlap command. Places a specified node on top of each column.
-- @module worldeditadditions.overlay -- @module worldeditadditions.overlay
function worldeditadditions.overlay(pos1, pos2, node_weights) 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 -- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area -- 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_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", "pos1: " .. worldeditadditions.vector.tostring(pos1))
-- minetest.log("action", "pos2: " .. worldeditadditions.vector.tostring(pos2)) -- 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 ******") -- print("\n\n[overlay] ****** column start ******")
for y = pos2.y, pos1.y, -1 do for y = pos2.y, pos1.y, -1 do
local i = area:index(x, y, z) 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_air = wea_c.is_airlike(data[i])
local is_liquid = worldeditadditions.is_liquidlike(data[i]) local is_liquid = wea_c.is_liquidlike(data[i])
-- wielded_light is now handled by worldeditadditions.is_airlike -- wielded_light is now handled by wea_c.is_airlike
local is_ignore = data[i] == node_id_ignore local is_ignore = data[i] == node_id_ignore

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

@ -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. -- @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. -- @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) 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 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)" 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 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.)" 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 end
local scale_down = { local scale_down = (1 / scale):floor()
x = math.floor(1 / scale.x), local size = pos2 - pos1
y = math.floor(1 / scale.y),
z = math.floor(1 / scale.z)
}
local size = vector.subtract(pos2, pos1)
if size.x < scale_down.x or size.y < scale_down.y or size.z < scale.z then 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 end
local size_small = { local size_small = (size / scale_down):floor()
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 manip, area = worldedit.manip_helpers.init(pos1, pos2) local manip, area = worldedit.manip_helpers.init(pos1, pos2)
local data = manip:get_data() 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 node_id_air = minetest.get_content_id("air")
local pos1_small = vector.new(pos1) local pos1_small = pos1:clone()
local pos2_small = vector.new(pos2) local pos2_small = pos2:clone()
if anchor.x < 1 then pos1_small.x = pos2_small.x - size_small.x 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 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 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 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*/)) -- posi_copy = vector.floor(vector.divide(posi_rel/*, scale_down*/))
local posi_copy = { local posi_copy = posi_rel / scale_down
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)
}
if anchor.x < 0 then posi_copy.x = size.x - posi_copy.x end 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.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 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_source = area:index(x, y, z)
local i_target = area:index(posi_copy.x, posi_copy.y, posi_copy.z) local i_target = area:index(posi_copy.x, posi_copy.y, posi_copy.z)

@ -95,7 +95,8 @@ function Vector3.mul(a, b) return Vector3.multiply(a, b) end
-- @returns Vector3 The result as a new Vector3 object. -- @returns Vector3 The result as a new Vector3 object.
function Vector3.divide(a, b) function Vector3.divide(a, b)
if type(a) == "number" then 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 elseif type(b) == "number" then
return Vector3.new(a.x / b, a.y / b, a.z / b) return Vector3.new(a.x / b, a.y / b, a.z / b)
end end