2022-09-19 18:27:59 +02:00
local wea_c = worldeditadditions_core
2022-09-19 01:18:03 +02:00
local Vector3 = wea_c.Vector3
2024-01-02 17:59:51 +01:00
---
-- @module worldeditadditions
2018-10-14 01:19:32 +02:00
--- Overlap command. Places a specified node on top of each column.
2023-07-07 02:25:42 +02:00
-- @param pos1 Vector3 pos1 of the defined region to perform the overlay operation in.
-- @param pos2 Vector3 pos2 of the defined region to perform the overlay operation in.
-- @param node_weights table<string,number> A table mapping (normalised) node names to their relative weight. Nodes with a higher weight are placed more often than those with a lower weighting.
-- Consider it like a ratio.
-- @returns table<string,number|table<number,number>> A table of statistics about the operation performed.
-- | Key | Value Type | Meaning |
-- |------------|---------------|---------------|
-- | `updated` | number | The number of nodes placed. |
-- | `skipped_columns` | number | The number of columns skipped. This could be because there is no airlike not in that column, or the top node is not airlike. |
-- | `placed` | table<number,number> | A map of node ids to the number of that node that was placed. |
2020-06-07 21:46:46 +02:00
function worldeditadditions . overlay ( pos1 , pos2 , node_weights )
2022-09-19 01:18:03 +02:00
pos1 , pos2 = Vector3.sort ( pos1 , pos2 )
2018-05-22 23:20:26 +02:00
-- pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the specified area
local manip , area = worldedit.manip_helpers . init ( pos1 , pos2 )
local data = manip : get_data ( )
2020-06-07 21:46:46 +02:00
local node_id_ignore = minetest.get_content_id ( " ignore " )
2022-09-19 01:18:03 +02:00
local node_ids , node_ids_count = wea_c.make_weighted ( node_weights )
2018-05-22 23:20:26 +02:00
2022-09-19 18:33:02 +02:00
-- minetest.log("action", "pos1: " .. pos1)
-- minetest.log("action", "pos2: " .. pos2)
2018-05-22 23:20:26 +02:00
-- z y x is the preferred loop order, but that isn't really possible here
2020-09-14 02:19:15 +02:00
local changes = { updated = 0 , skipped_columns = 0 , placed = { } }
2018-05-22 23:20:26 +02:00
for z = pos2.z , pos1.z , - 1 do
for x = pos2.x , pos1.x , - 1 do
local found_air = false
local placed_node = false
2021-03-02 01:09:46 +01:00
-- print("\n\n[overlay] ****** column start ******")
2018-05-22 23:20:26 +02:00
for y = pos2.y , pos1.y , - 1 do
2020-06-07 21:46:46 +02:00
local i = area : index ( x , y , z )
2022-09-19 01:18:03 +02:00
-- 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]))
2020-06-07 21:46:46 +02:00
2022-09-19 01:18:03 +02:00
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
2020-09-14 02:19:15 +02:00
2020-06-07 21:46:46 +02:00
local is_ignore = data [ i ] == node_id_ignore
if not is_air and not is_ignore then
2021-03-02 01:09:46 +01:00
local i_above = area : index ( x , y + 1 , z )
if found_air and not is_liquid then
2020-06-07 21:46:46 +02:00
local new_id = node_ids [ math.random ( node_ids_count ) ]
2018-05-22 23:20:26 +02:00
-- We've found an air block previously, so it must be above us
-- Replace the node above us with the target block
2021-03-02 01:09:46 +01:00
data [ i_above ] = new_id
2018-05-22 23:20:26 +02:00
changes.updated = changes.updated + 1
placed_node = true
2020-09-14 02:19:15 +02:00
if not changes.placed [ new_id ] then
changes.placed [ new_id ] = 0
end
changes.placed [ new_id ] = changes.placed [ new_id ] + 1
2021-03-02 01:09:46 +01:00
-- print("[overlay] placed above ", x, y, z)
2018-05-22 23:20:26 +02:00
break -- Move on to the next column
end
2021-03-02 01:09:46 +01:00
elseif not is_ignore and not is_liquid then
-- print("[overlay] found air at", x, y, z)
2018-05-22 23:20:26 +02:00
found_air = true
end
2021-03-02 01:09:46 +01:00
if is_liquid then found_air = false end
2018-05-22 23:20:26 +02:00
end
if not placed_node then
changes.skipped_columns = changes.skipped_columns + 1
end
end
end
-- Save the modified nodes back to disk & return
worldedit.manip_helpers . finish ( manip , data )
return changes
end