diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index a7c10f8..e96fa9f 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -18,6 +18,7 @@ dofile(worldeditadditions.modpath.."/utils/raycast_adv.lua") -- For the farwand dofile(worldeditadditions.modpath.."/lib/floodfill.lua") dofile(worldeditadditions.modpath.."/lib/overlay.lua") dofile(worldeditadditions.modpath.."/lib/layers.lua") +dofile(worldeditadditions.modpath.."/lib/fillcaves.lua") dofile(worldeditadditions.modpath.."/lib/ellipsoid.lua") dofile(worldeditadditions.modpath.."/lib/torus.lua") dofile(worldeditadditions.modpath.."/lib/walls.lua") diff --git a/worldeditadditions/lib/fillcaves.lua b/worldeditadditions/lib/fillcaves.lua new file mode 100644 index 0000000..debb983 --- /dev/null +++ b/worldeditadditions/lib/fillcaves.lua @@ -0,0 +1,55 @@ +--- Overlap command. Places a specified node on top of each column. +-- @module worldeditadditions.overlay + +function worldeditadditions.fillcaves(pos1, pos2, node_name) + pos1, pos2 = worldedit.sort_pos(pos1, pos2) + -- 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_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)) + + -- z y x is the preferred loop order, but that isn't really possible here + + local changes = { replaced = 0 } + for z = pos2.z, pos1.z, -1 do + for x = pos2.x, pos1.x, -1 do + local is_first_node_in_col = true + local prev_is_air = false + local found_toplayer = false + + for y = pos2.y, pos1.y, -1 do + local i = area:index(x, y, z) + + local is_air = worldeditadditions.is_airlike(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 + if prev_is_air and not is_air then + found_toplayer = true + elseif is_first_node_in_col and not is_air then + found_toplayer = true + elseif found_toplayer and is_air and not is_ignore then + -- We've found the top layer already and this node is air, + -- so we should fill it in + data[i] = node_id_replace + changes.replaced = changes.replaced + 1 + end + + is_first_node_in_col = false + prev_is_air = is_air + end + end + end + + -- Save the modified nodes back to disk & return + worldedit.manip_helpers.finish(manip, data) + + return true, changes +end diff --git a/worldeditadditions_commands/commands/fillcaves.lua b/worldeditadditions_commands/commands/fillcaves.lua new file mode 100644 index 0000000..3a764a7 --- /dev/null +++ b/worldeditadditions_commands/commands/fillcaves.lua @@ -0,0 +1,36 @@ +-- ███████ ██ ██ ██ ██████ █████ ██ ██ ███████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- █████ ██ ██ ██ ██ ███████ ██ ██ █████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ███████ ███████ ██████ ██ ██ ████ ███████ ███████ +worldedit.register_command("fillcaves", { + params = "[]", + description = "Fills in all airlike nodes beneath the first non-airlike node detected in each column.", + privs = { worldedit = true }, + require_pos = 2, + parse = function (params_text) + if params_text == "" then + params_text = "stone" + end + local replace_node = worldedit.normalize_nodename(params_text) + if not replace_node then + return false, "Error: Invalid node name." + end + + return true, replace_node + end, + nodes_needed = function(name) + return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name]) + end, + func = function(name, replace_node) + local start_time = worldeditadditions.get_ms_time() + + local success, stats = worldeditadditions.fillcaves(worldedit.pos1[name], worldedit.pos2[name], replace_node) + if not success then return success, stats end + + local time_taken = worldeditadditions.get_ms_time() - start_time + + minetest.log("action", name .. " used //fillcaves at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. stats.replaced .. " nodes in " .. time_taken .. "s") + return true, stats.replaced .. " nodes replaced in " .. worldeditadditions.human_time(time_taken) + end +}) diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index 229f460..0c7d879 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -24,6 +24,7 @@ dofile(we_c.modpath.."/many.lua") dofile(we_c.modpath.."/commands/floodfill.lua") dofile(we_c.modpath.."/commands/overlay.lua") dofile(we_c.modpath.."/commands/layers.lua") +dofile(we_c.modpath.."/commands/fillcaves.lua") dofile(we_c.modpath.."/commands/ellipsoid.lua") dofile(we_c.modpath.."/commands/torus.lua") dofile(we_c.modpath.."/commands/walls.lua")