local function disintigrate(pos, radius, node_name, user_name, dropped) local node_id = minetest.get_content_id(node_name) local air = minetest.get_content_id('air') local minp = vector.subtract(pos, radius) local maxp = vector.add(pos, radius) local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local data = vm:get_data() local count = 0 local drops = {} local p = {} for z = minp.z, maxp.z do p.z = z for y = minp.y, maxp.y do p.y = y local ivm = area:index(minp.x, y, z) for x = minp.x, maxp.x do p.x = x if data[ivm] == node_id and not minetest.is_protected(p, user_name) then data[ivm] = air count = count + 1 if count % 50 == 0 then drops[#drops+1] = table.copy(p) end end ivm = ivm + 1 end end end vm:set_data(data) vm:write_to_map() vm:update_map() count = math.floor(count / 3) for _, p in pairs(drops) do if count < 1 then return end local dropitem = ItemStack(dropped or node_name) local take = math.min(count, dropitem:get_stack_max()) dropitem:set_count(take) local obj = minetest.add_item(p, dropitem) if obj then count = count - take end end end local function floor(pos, blocks, node_name, user_name) local p = {y = pos.y} local count = 0 for r = 1, blocks do for z = -r, r do p.z = pos.z + z for x = -r, r do p.x = pos.x + x local node = minetest.get_node_or_nil(p) if node and (node.name == 'air' or node.name == 'default:water_source') and not minetest.is_protected(p, user_name) then minetest.set_node(p, {name = node_name}) count = count + 1 if count > blocks then return end end end end end end -- Bombs local nodes = {{'fun_caves:pyramid_1', 'default:sandstone'}, {'fun_caves:tree', 'fun_caves:tree'}, {'default:stone', 'default:cobble'},} for _, node in pairs(nodes) do local node_name = node[1] local comp = node[2] or node_name local node_texture = minetest.registered_items[node_name].tiles if type(node_texture) == 'table' then node_texture = node_texture[1] end local newnode = fun_caves.clone_node(node_name) local _, d_name = node_name:match('(.*:)(.*)') local bomb_name = "fun_caves:"..d_name..'_bomb' local d_name_u = d_name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end) newnode.description = d_name_u.." Bomb" newnode.tiles = {'tnt_top.png', 'tnt_bottom.png', newnode.tiles[1]} newnode.inventory_image = '[inventorycube{tnt_top.png{'..node_texture..'{tnt_side.png' newnode.drop = bomb_name newnode.on_punch = function(pos, node, puncher, pointed_thing) if puncher:get_wielded_item():get_name() ~= "default:torch" then return end minetest.after(5, function() local pos_node = minetest.get_node_or_nil(pos) if pos_node.name ~= bomb_name then return end disintigrate(pos, 5, node_name, puncher:get_player_name(), comp) minetest.remove_node(pos) end) end minetest.register_node(bomb_name, newnode) minetest.register_craft({ output = "fun_caves:"..d_name..'_bomb', recipe = { {"", comp, ""}, {comp, "tnt:gunpowder", comp}, {"", comp, ""} } }) end -- Floor bombs local nodes = {{'default:sandstone', 'default:sandstone_block'}, {'default:wood', 'fun_caves:wood_block'}, {'default:stone', 'default:stone_block'},} for _, node in pairs(nodes) do local node_name = node[1] local comp = node[2] or node_name local node_texture = minetest.registered_items[node_name].tiles if type(node_texture) == 'table' then node_texture = node_texture[1] end local _, d_name = node_name:match('(.*:)(.*)') local bomb_name = "fun_caves:"..d_name..'_floor_bomb' local d_name_u = d_name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end) local newnode = fun_caves.clone_node(node_name) newnode.description = d_name_u.." Floor Bomb" newnode.inventory_image = '[inventorycube{'..node_texture..'{'..node_texture..'{'..node_texture..'^fun_caves_expand.png' newnode.drop = bomb_name newnode.on_punch = function(pos, node, puncher, pointed_thing) if puncher:get_wielded_item():get_name() ~= "default:torch" then return end minetest.after(5, function() local pos_node = minetest.get_node_or_nil(pos) if pos_node.name ~= bomb_name then return end floor(pos, 100, node_name, puncher:get_player_name()) minetest.set_node(pos, {name = node_name}) end) end minetest.register_node(bomb_name, newnode) if not minetest.registered_items[comp] then newnode = fun_caves.clone_node(node_name) newnode.description = newnode.description .. ' Block' minetest.register_node(comp, newnode) minetest.register_craft({ output = comp, recipe = { {node_name, node_name, node_name}, {node_name, node_name, node_name}, {node_name, node_name, node_name} } }) end minetest.register_craft({ output = "fun_caves:"..d_name..'_floor_bomb', recipe = { {comp, comp, comp}, {comp, "tnt:gunpowder", comp}, {comp, comp, comp} } }) end local mass_nodes = {'fun_caves:tree', 'default:tree', 'default:jungletree', 'default:acacia_tree', 'default:aspen_tree', 'default:stone', 'default:sandstone', 'default:desert_stone', 'fun_caves:stone_with_algae', 'fun_caves:stone_with_moss', 'fun_caves:stone_with_lichen'} local mass_tools_list = {'default:axe_bronze', 'default:axe_diamond', 'default:axe_mese', 'default:pick_bronze', 'default:pick_diamond', 'default:pick_mese'} local mass_tools = {} for _, tool in pairs(mass_tools_list) do mass_tools[tool] = true end local mass_minerals_list = {'default:gravel'} local mass_minerals = {} for _, min in pairs(mass_minerals_list) do mass_minerals[min] = true end for name, _ in pairs(minetest.registered_nodes) do if name:find('stone_with') then mass_minerals[name] = true end end local function default_rightclick(pos, node, clicker, itemstack, pointed_thing) if itemstack:get_definition().type == "node" then return minetest.item_place_node(itemstack, clicker, pointed_thing) end return itemstack end for _, node in pairs(mass_nodes) do minetest.override_item(node, {on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) local tool = itemstack:get_name() if not mass_tools[tool] then return default_rightclick(pos, node, clicker, itemstack, pointed_thing) end local tool_type, maxr if tool:find('axe') then if minetest.get_item_group(node.name, "tree") == 0 then return default_rightclick(pos, node, clicker, itemstack, pointed_thing) end tool_type = 'axe' maxr = {x = 2, y = 20, z = 2} elseif tool:find('pick') then if node.name ~= 'default:sandstone' and minetest.get_item_group(node.name, "stone") == 0 then return default_rightclick(pos, node, clicker, itemstack, pointed_thing) end tool_type = 'pick' maxr = {x = 2, y = 4, z = 2} else return default_rightclick(pos, node, clicker, itemstack, pointed_thing) end local player_pos = vector.round(clicker:getpos()) local player_name = clicker:get_player_name() local inv = clicker:get_inventory() if not (player_pos and player_name and inv) then return default_rightclick(pos, node, clicker, itemstack, pointed_thing) end pos = vector.round(pos) local max_nodes = 60 local minp = vector.subtract(pos, 2) local maxp = vector.add(pos, maxr) if pos.y >= player_pos.y then minp.y = player_pos.y if pos.y - player_pos.y < 3 then maxp.y = player_pos.y + 3 end end local air = minetest.get_content_id('air') local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local data = vm:get_data() local drops = {} local names = {} local diggable = {} local tree_like = {} local leaf_like = {} local stone_like = {} local count = 0 local p = {} for y = minp.y, maxp.y do p.y = y for z = minp.z, maxp.z do p.z = z local ivm = area:index(minp.x, y, z) for x = minp.x, maxp.x do p.x = x if not names[data[ivm]] then names[data[ivm]] = minetest.get_name_from_content_id(data[ivm]) end if not diggable[data[ivm]] then if tool_type == 'axe' then diggable[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'choppy') or 0 diggable[data[ivm]] = diggable[data[ivm]] + minetest.get_item_group(names[data[ivm]], 'snappy') or 0 diggable[data[ivm]] = diggable[data[ivm]] + minetest.get_item_group(names[data[ivm]], 'fleshy') or 0 elseif tool_type == 'pick' then diggable[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'cracky') or 0 end end if not stone_like[data[ivm]] then stone_like[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'stone') or 0 stone_like[data[ivm]] = stone_like[data[ivm]] + (names[data[ivm]] == 'default:sandstone' and 1 or 0) end if not tree_like[data[ivm]] then tree_like[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'tree') or 0 end if not leaf_like[data[ivm]] then leaf_like[data[ivm]] = minetest.get_item_group(names[data[ivm]], 'leafdecay') or 0 end local dig_it if tool_type == 'axe' then dig_it = tree_like[data[ivm]] > 0 or leaf_like[data[ivm]] > 0 elseif tool_type == 'pick' then dig_it = stone_like[data[ivm]] > 0 or mass_minerals[names[data[ivm]]] end if count < max_nodes and diggable[data[ivm]] > 0 and dig_it and not minetest.is_protected(p, player_name) then drops[data[ivm]] = (drops[data[ivm]] or 0) + 1 data[ivm] = air count = count + 1 end ivm = ivm + 1 end end end vm:set_data(data) vm:write_to_map() vm:update_map() for id, number in pairs(drops) do for i = 1, number do local drops = minetest.get_node_drops(names[id], tool) minetest.handle_node_drops(pos, drops, clicker) end local tp = itemstack:get_tool_capabilities() local def = ItemStack({name=names[id]}):get_definition() local dp = minetest.get_dig_params(def.groups, tp) --print(names[id], dp.wear, number) itemstack:add_wear(dp.wear * number) end return itemstack end, }) end