diff --git a/spec_bomb.lua b/spec_bomb.lua index 549c9e2..466427a 100644 --- a/spec_bomb.lua +++ b/spec_bomb.lua @@ -171,3 +171,148 @@ for _, node in pairs(nodes) do } }) 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 + 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