diff --git a/init.lua b/init.lua index 9f7da01..f0a0d60 100644 --- a/init.lua +++ b/init.lua @@ -5,6 +5,7 @@ local MP = minetest.get_modpath("pick_and_place") dofile(MP .. "/common.lua") dofile(MP .. "/pointed.lua") dofile(MP .. "/configure.lua") +dofile(MP .. "/remove.lua") dofile(MP .. "/serialize.lua") dofile(MP .. "/entity.lua") dofile(MP .. "/handle_node.lua") diff --git a/place_tool.lua b/place_tool.lua index df47b13..d034968 100644 --- a/place_tool.lua +++ b/place_tool.lua @@ -7,19 +7,31 @@ minetest.register_tool("pick_and_place:place", { not_in_creative_inventory = 1 }, on_use = function(itemstack, player) + local playername = player:get_player_name() + local controls = player:get_player_control() + local meta = itemstack:get_meta() local schematic = meta:get_string("schematic") local size = minetest.string_to_pos(meta:get_string("size")) local distance = vector.distance(vector.new(), size) local pos1 = pick_and_place.get_pointed_position(player, math.max(10, distance) + 5) - local success, msg = pick_and_place.deserialize(pos1, schematic) - if not success then - minetest.chat_send_player(player:get_player_name(), "Placement error: " .. msg) + local pos2 = vector.add(pos1, vector.subtract(size, 1)) + + if controls.aux1 then + -- removal + pick_and_place.remove_area(pos1, pos2) + else + -- placement + local success, msg = pick_and_place.deserialize(pos1, schematic) + if not success then + minetest.chat_send_player(playername, "Placement error: " .. msg) + end end end, on_step = function(itemstack, player) local playername = player:get_player_name() + local controls = player:get_player_control() local meta = itemstack:get_meta() local size = minetest.string_to_pos(meta:get_string("size")) @@ -28,7 +40,13 @@ minetest.register_tool("pick_and_place:place", { local pos1 = pick_and_place.get_pointed_position(player, math.max(10, distance) + 5) local pos2 = vector.add(pos1, vector.subtract(size, 1)) - pick_and_place.show_preview(playername, "pick_and_place_plus.png", "#0000ff", pos1, pos2) + if controls.aux1 then + -- removal preview + pick_and_place.show_preview(playername, "pick_and_place_minus.png", "#ff0000", pos1, pos2) + else + -- build preview + pick_and_place.show_preview(playername, "pick_and_place_plus.png", "#0000ff", pos1, pos2) + end end, on_deselect = function(_, player) local playername = player:get_player_name() diff --git a/readme.md b/readme.md index bf9aa04..7283265 100644 --- a/readme.md +++ b/readme.md @@ -22,6 +22,8 @@ Simple copy+paste operation * This will convert the pick-tool to a blue `pick_and_place:place` tool in your inventory * Use the place-tool to place your build anywhere in the world with the help of the preview-overlay +**Pro-tip**: hold the `aux` key to switch to removal-mode + ## Configure a template area Create a template for frequent reuse diff --git a/remove.lua b/remove.lua new file mode 100644 index 0000000..22ac94b --- /dev/null +++ b/remove.lua @@ -0,0 +1,31 @@ +local air_cid = minetest.get_content_id("air") + +function pick_and_place.remove_area(pos1, pos2) + local manip = minetest.get_voxel_manip() + local e1, e2 = manip:read_from_map(pos1, pos2) + local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2}) + + local node_data = manip:get_data() + local param2 = manip:get_param2_data() + + for z=pos1.z,pos2.z do + for x=pos1.x,pos2.x do + for y=pos1.y,pos2.y do + local i = area:index(x,y,z) + node_data[i] = air_cid + param2[i] = 0 + end + end + end + + manip:set_data(node_data) + manip:set_param2_data(param2) + manip:write_to_map() + + -- clear metadata + local nodes_with_meta = minetest.find_nodes_with_meta(pos1, pos2) + for _, pos in ipairs(nodes_with_meta) do + local meta = minetest.get_meta(pos) + meta:from_table({}) + end +end \ No newline at end of file diff --git a/textures/pick_and_place_minus.png b/textures/pick_and_place_minus.png new file mode 100644 index 0000000..6018b30 Binary files /dev/null and b/textures/pick_and_place_minus.png differ