From 1c2efd0153935cdc0e4a366f2c547f611080e326 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sun, 14 Oct 2018 21:00:08 +0100 Subject: [PATCH] //replace: Addmixed block support --- ChatCommands.md | 8 ++- worldedit/manipulations.lua | 32 ++++++++-- worldedit_commands/init.lua | 117 +++++++++++++++++++++++++++++------- 3 files changed, 128 insertions(+), 29 deletions(-) diff --git a/ChatCommands.md b/ChatCommands.md index 4bcb24f..1b290f4 100644 --- a/ChatCommands.md +++ b/ChatCommands.md @@ -134,21 +134,25 @@ Fill the current WorldEdit region with a random mix of ``, ``, `.. ### `//replace ` -Replace all instances of `` with `` in the current WorldEdit region. +Replace all instances of `` with `` in the current WorldEdit region. `` can be in the same format as `//mix`. //replace Cobblestone air //replace lightstone_blue glass //replace dirt Bronze Block //replace mesecons:wire_00000000_off flowers:flower_tulip + //replace dirt snowblock 5 ice 2 + //replace dirt_with_grass sand 10 silver_sand 3 desert_sand ### `//replaceinverse ` -Replace all nodes other than `` with `` in the current WorldEdit region. +Replace all nodes other than `` with `` in the current WorldEdit region. `` can be in the same format as `//mix`. //replaceinverse Cobblestone air //replaceinverse flowers:flower_waterlily glass //replaceinverse dirt Bronze Block //replaceinverse mesecons:wire_00000000_off flowers:flower_tulip + //replaceinverse dirt snowblock 5 ice 2 + //replaceinverse dirt_with_grass sand 10 silver_sand 3 desert_sand ### `//hollowcube ` diff --git a/worldedit/manipulations.lua b/worldedit/manipulations.lua index ee51561..2646d51 100644 --- a/worldedit/manipulations.lua +++ b/worldedit/manipulations.lua @@ -72,24 +72,45 @@ function worldedit.replace(pos1, pos2, search_node, replace_node, inverse) local data = manip:get_data() local search_id = minetest.get_content_id(search_node) - local replace_id = minetest.get_content_id(replace_node) - + + local replace_multiple = not (type(replace_node) == "string") + local replace_id = nil, id_count, rand + + if not replace_multiple then + replace_id = minetest.get_content_id(replace_node) + else + id_count, rand = #replace_node, math.random + replace_id = {} + for i, node_name in ipairs(replace_node) do + replace_id[i] = minetest.get_content_id(node_name) + end + end + + local count = 0 --- TODO: This could be shortened by checking `inverse` in the loop, - -- but that would have a speed penalty. Is the penalty big enough + -- but that would have a speed penalty. Is the penalty big enough -- to matter? if not inverse then for i in area:iterp(pos1, pos2) do if data[i] == search_id then - data[i] = replace_id + if not replace_multiple then + data[i] = replace_id + else + data[i] = replace_id[rand(id_count)] + end count = count + 1 end end else for i in area:iterp(pos1, pos2) do if data[i] ~= search_id then - data[i] = replace_id + if not replace_multiple then + data[i] = replace_id + else + data[i] = replace_id[rand(id_count)] + end count = count + 1 end end @@ -646,4 +667,3 @@ function worldedit.clear_objects(pos1, pos2) end return count end - diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index e415865..5a568ec 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -453,21 +453,35 @@ minetest.register_chatcommand("/mix", { }) local check_replace = function(name, param) - local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") - if found == nil then - worldedit.player_notify(name, "invalid usage: " .. param) - return nil + local search_node = nil + local replace_nodes = {} + for nodename in param:gmatch("[^%s]+") do + if search_node == nil then + search_node = get_node(name, nodename) + else + if tonumber(nodename) ~= nil then + local last_node = replace_nodes[#replace_nodes] + local node_count = tonumber(nodename) + minetest.log("action", "last node: " .. last_node .. ", count: " .. node_count) + + for i=1,node_count do + replace_nodes[#replace_nodes + 1] = last_node + end + else + local node = get_node(name, nodename) + if not node then + worldedit.player_notify(name, "invalid replace node name: " .. searchnode) + return nil + end + replace_nodes[#replace_nodes + 1] = node + end + end end - local newsearchnode = worldedit.normalize_nodename(searchnode) - if not newsearchnode then + + if not search_node then worldedit.player_notify(name, "invalid search node name: " .. searchnode) return nil end - local newreplacenode = worldedit.normalize_nodename(replacenode) - if not newreplacenode then - worldedit.player_notify(name, "invalid replace node name: " .. replacenode) - return nil - end return check_region(name, param) end @@ -476,11 +490,41 @@ minetest.register_chatcommand("/replace", { description = "Replace all instances of with in the current WorldEdit region", privs = {worldedit=true}, func = safe_region(function(name, param) - local found, _, search_node, replace_node = param:find("^([^%s]+)%s+(.+)$") - local norm_search_node = worldedit.normalize_nodename(search_node) - local norm_replace_node = worldedit.normalize_nodename(replace_node) - local count = worldedit.replace(worldedit.pos1[name], worldedit.pos2[name], - norm_search_node, norm_replace_node) + local search_node = nil + local replace_nodes = {} + for nodename in param:gmatch("[^%s]+") do + worldedit.player_notify(name, "Processing "..nodename) + if search_node == nil then + search_node = get_node(name, nodename) + else + if tonumber(nodename) ~= nil then + local last_node = replace_nodes[#replace_nodes] + local node_count = tonumber(nodename) + minetest.log("action", "last node: " .. last_node .. ", count: " .. node_count) + + for i=1,node_count do + replace_nodes[#replace_nodes + 1] = last_node + end + else + local node = get_node(name, nodename) + if not node then return end + replace_nodes[#replace_nodes + 1] = node + end + end + end + + local count + if #replace_nodes == 1 then + count = worldedit.replace( + worldedit.pos1[name], worldedit.pos2[name], + search_node, replace_nodes[1] + ) + else + count = worldedit.replace( + worldedit.pos1[name], worldedit.pos2[name], + search_node, replace_nodes + ) + end worldedit.player_notify(name, count .. " nodes replaced") end, check_replace), }) @@ -490,11 +534,42 @@ minetest.register_chatcommand("/replaceinverse", { description = "Replace all nodes other than with in the current WorldEdit region", privs = {worldedit=true}, func = safe_region(function(name, param) - local found, _, search_node, replace_node = param:find("^([^%s]+)%s+(.+)$") - local norm_search_node = worldedit.normalize_nodename(search_node) - local norm_replace_node = worldedit.normalize_nodename(replace_node) - local count = worldedit.replace(worldedit.pos1[name], worldedit.pos2[name], - norm_search_node, norm_replace_node, true) + local search_node = nil + local replace_nodes = {} + for nodename in param:gmatch("[^%s]+") do + if search_node == nil then + search_node = get_node(name, nodename) + else + if tonumber(nodename) ~= nil then + local last_node = replace_nodes[#replace_nodes] + local node_count = tonumber(nodename) + minetest.log("action", "last node: " .. last_node .. ", count: " .. node_count) + + for i=1,node_count do + replace_nodes[#replace_nodes + 1] = last_node + end + else + local node = get_node(name, nodename) + if not node then return end + replace_nodes[#replace_nodes + 1] = node + end + end + end + + local count + if #replace_nodes == 1 then + count = worldedit.replace( + worldedit.pos1[name], worldedit.pos2[name], + search_node, replace_nodes[1], + true + ) + else + count = worldedit.replace( + worldedit.pos1[name], worldedit.pos2[name], + search_node, replace_nodes, + true + ) + end worldedit.player_notify(name, count .. " nodes replaced") end, check_replace), })