local wea_c = worldeditadditions_core local Vector3 = wea_c.Vector3 -- ██ █████ ██ ██ ███████ ██████ ███████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ███████ ████ █████ ██████ ███████ -- ██ ██ ██ ██ ██ ██ ██ ██ -- ███████ ██ ██ ██ ███████ ██ ██ ███████ local function print_slopes(slopemap, width) local copy = wea_c.table.shallowcopy(slopemap) for key,value in pairs(copy) do copy[key] = wea_c.round(math.deg(value), 2) end 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. -- @param pos1 Vector Position 1 of the region to operate on -- @param pos2 Vector Position 2 of the region to operate on -- @param node_weights string[] -- @param min_slope number? -- @param max_slope number? function worldeditadditions.layers(pos1, pos2, node_weights, min_slope, max_slope) 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 -- Fetch the nodes in the specified area local manip, area = worldedit.manip_helpers.init(pos1, pos2) local data = manip:get_data() local node_id_ignore = minetest.get_content_id("ignore") local node_ids, node_ids_count = wea_c.unwind_node_list(node_weights) local heightmap, heightmap_size = wea_c.terrain.make_heightmap( pos1, pos2, manip, area, data ) local slopemap = wea_c.terrain.calculate_slopes(heightmap, heightmap_size) -- wea_c.format.array_2d(heightmap, heightmap_size.x) -- print_slopes(slopemap, heightmap_size.x) --luacheck:ignore 311 heightmap = nil -- Just in case Lua wants to garbage collect it -- minetest.log("action", "pos1: " .. pos1) -- minetest.log("action", "pos2: " .. pos2) -- for i,v in ipairs(node_ids) do -- print("[layer] i", i, "node id", v) -- end -- z y x is the preferred loop order, but that isn't really possible here local changes = { replaced = 0, skipped_columns = 0, skipped_columns_slope = 0 } for z = pos2.z, pos1.z, -1 do for x = pos2.x, pos1.x, -1 do local next_index = 1 -- We use table.insert() in make_weighted local placed_node = false local hi = (z-pos1.z)*heightmap_size.x + (x-pos1.x) -- print("DEBUG hi", hi, "x", x, "z", z, "slope", slopemap[hi], "as deg", math.deg(slopemap[hi])) -- Again, Lua 5.1 doesn't have a continue statement :-/ if slopemap[hi] >= min_slope and slopemap[hi] <= max_slope then for y = pos2.y, pos1.y, -1 do local i = area:index(x, y, z) 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 -- It's not an airlike node or something else odd data[i] = node_ids[next_index] next_index = next_index + 1 changes.replaced = changes.replaced + 1 -- If we're done replacing nodes in this column, move to the next one if next_index > #node_ids then break end end end else changes.skipped_columns_slope = changes.skipped_columns_slope + 1 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