code:
local S = minetest.get_translator(minetest.get_current_modname())

-----------------------------------------------------------------------
-- Plants

minetest.register_node("df_farming:dead_fungus", {
	description = S("Dead Fungus"),
	_doc_items_longdesc = df_farming.doc.dead_fungus_desc,
	_doc_items_usagehelp = df_farming.doc.dead_fungus_usage,
	drawtype = "plantlike",
	tiles = {"dfcaverns_dead_fungus.png"},
	inventory_image = "dfcaverns_dead_fungus.png",
	paramtype = "light",
	walkable = false,
	is_ground_content = false,
	buildable_to = true,
	floodable = true,
	groups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, flow_through = 1, fire_encouragement=60,fire_flammability=100,destroy_by_lava_flow=1,dig_by_piston=1, compostability=65, handy=1, hoey=1},
	sounds = df_dependencies.sound_leaves(),
	selection_box = {
		type = "fixed",
		fixed = {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
	},
	_mcl_blast_resistance = 0.2,
	_mcl_hardness = 0.2,
})

minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:dead_fungus",
	burntime = 2
})

local c_dead_fungus = minetest.get_content_id("df_farming:dead_fungus")
df_farming.spawn_dead_fungus_vm = function(vi, area, data, param2_data)
	data[vi] = c_dead_fungus
	param2_data[vi] = 0
end

minetest.register_node("df_farming:cavern_fungi", {
	description = S("Cavern Fungi"),
	_doc_items_longdesc = df_farming.doc.cavern_fungi_desc,
	_doc_items_usagehelp = df_farming.doc.cavern_fungi_usage,
	drawtype = "plantlike",
	tiles = {"dfcaverns_fungi.png"},
	inventory_image = "dfcaverns_fungi.png",
	paramtype = "light",
	walkable = false,
	is_ground_content = false,
	buildable_to = true,
	floodable = true,
	light_source = 6,
	groups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, light_sensitive_fungus = 11, flow_through = 1, fire_encouragement=50,fire_flammability=60,destroy_by_lava_flow=1,dig_by_piston=1, compostability=65, handy=1, hoey=1},
	sounds = df_dependencies.sound_leaves(),
	selection_box = {
		type = "fixed",
		fixed = {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
	},
	_mcl_blast_resistance = 0.2,
	_mcl_hardness = 0.2,
})

minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:cavern_fungi",
	burntime = 2
})

local c_cavern_fungi = minetest.get_content_id("df_farming:cavern_fungi")
df_farming.spawn_cavern_fungi_vm = function(vi, area, data, param2_data)
	data[vi] = c_cavern_fungi
	param2_data[vi] = 0
end

-----------------------------------------------------------------------------------------

local marginal = {[df_dependencies.node_name_dirt] = true}
local growable = {[df_dependencies.node_name_dirt_wet] = true, [df_dependencies.node_name_dirt] = true}

df_farming.plant_timer = function(pos, plantname, elapsed)
	local next_stage_time = minetest.registered_nodes[plantname]._dfcaverns_next_stage_time
	if not next_stage_time then return end

	next_stage_time = next_stage_time + math.random(next_stage_time * -0.1, next_stage_time * 0.1)
	local below = minetest.get_node(vector.add(pos, {x=0, y=-1, z=0}))
	if marginal[below.name] then
		next_stage_time = next_stage_time * 5
	end
	if elapsed ~= nil then
		minetest.get_node_timer(pos):set(next_stage_time, elapsed-next_stage_time)
	else
		minetest.get_node_timer(pos):start(next_stage_time)
	end
end

local function copy_pointed_thing(pointed_thing)
	return {
		type  = pointed_thing.type,
		above = pointed_thing.above and vector.copy(pointed_thing.above),
		under = pointed_thing.under and vector.copy(pointed_thing.under),
		ref   = pointed_thing.ref,
	}
end

local place_seed = function(itemstack, placer, pointed_thing, plantname)
	local pt = pointed_thing
	-- check if pointing at a node
	if not pt then
		return itemstack
	end
	if pt.type ~= "node" then
		return itemstack
	end

	local under = minetest.get_node(pt.under)
	local above = minetest.get_node(pt.above)

	if minetest.is_protected(pt.under, placer:get_player_name()) then
		minetest.record_protection_violation(pt.under, placer:get_player_name())
		return
	end
	if minetest.is_protected(pt.above, placer:get_player_name()) then
		minetest.record_protection_violation(pt.above, placer:get_player_name())
		return
	end

	-- return if any of the nodes is not registered
	if not minetest.registered_nodes[under.name] then
		return itemstack
	end
	if not minetest.registered_nodes[above.name] then
		return itemstack
	end

	-- check if pointing at the top of the node
	if pt.above.y ~= pt.under.y+1 then
		return itemstack
	end

	-- check if you can replace the node above the pointed node
	if not minetest.registered_nodes[above.name].buildable_to then
		return itemstack
	end

	-- add the node and remove 1 item from the itemstack
	local newnode= {name = itemstack:get_name(), param2 = 1, param1=0}
	local oldnode= minetest.get_node(pt.above)
	minetest.add_node(pt.above, {name = plantname, param2 = 1})

	local growth_permitted_function = df_farming.growth_permitted[plantname]
	if not growth_permitted_function or growth_permitted_function(pt.above) then
		df_farming.plant_timer(pt.above, plantname)
	else
		minetest.get_node_timer(pt.above):stop() -- make sure no old timers are running on this node
	end

	-- Run script hook
	local take_item = true
	for _, callback in ipairs(core.registered_on_placenodes) do
		-- Deepcopy pos, node and pointed_thing because callback can modify them
		local place_to_copy = vector.copy(pt.above)
		local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
		local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
		local pointed_thing_copy = copy_pointed_thing(pointed_thing)
		if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then
			take_item = false
		end
	end

	if not minetest.is_creative_enabled(placer:get_player_name()) then
		itemstack:take_item()
	end
	return itemstack
end

df_farming.register_seed = function(name, description, image, stage_one, grow_time, desc, usage)
	local def = {
		description = description,
		_doc_items_longdesc = desc,
		_doc_items_usagehelp = usage,
		tiles = {image},
		inventory_image = image,
		wield_image = image,
		drawtype = "signlike",
		paramtype2 = "wallmounted",
		groups = {seed = 1, snappy = 3, attached_node = 1, dfcaverns_cookable = 1, digtron_on_place=1,destroy_by_lava_flow=1,dig_by_piston=1, handy=1, hoey=1},
		_dfcaverns_next_stage = stage_one,
		_dfcaverns_next_stage_time = grow_time,
		paramtype = "light",
		walkable = false,
		is_ground_content = false,
		floodable = true,
		sunlight_propagates = true,
		selection_box = {
			type = "fixed",
			fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
		},
		_mcl_blast_resistance = 0.2,
		_mcl_hardness = 0.2,

		on_place = function(itemstack, placer, pointed_thing)
			return place_seed(itemstack, placer, pointed_thing, "df_farming:"..name)
		end,

		on_timer = function(pos, elapsed)
			df_farming.grow_underground_plant(pos, "df_farming:"..name, elapsed)
		end,

		on_destruct = function(pos)
			minetest.get_node_timer(pos):stop()
		end,
	}

	minetest.register_node("df_farming:"..name, def)
	minetest.register_craft({
		type = "fuel",
		recipe = "df_farming:"..name,
		burntime = 1
	})
end

df_farming.grow_underground_plant = function(pos, plant_name, elapsed)
	if df_farming.kill_if_sunlit(pos) then
		return
	end
	local node_def = minetest.registered_nodes[plant_name]
	local next_stage = node_def._dfcaverns_next_stage
	if next_stage then
		local soil = minetest.get_node(vector.add(pos, {x=0, y=-1, z=0})).name
		if growable[soil] then
			local next_def = minetest.registered_nodes[next_stage]
			local node = minetest.get_node(pos)
			minetest.swap_node(pos, {name=next_stage, param2 = next_def.place_param2 or node.param2})
			df_farming.plant_timer(pos, next_stage, elapsed)
		else
			df_farming.plant_timer(pos, plant_name) -- reset timer, check again later
		end
	end
end

df_farming.kill_if_sunlit = function(pos, node)
	return false
end
if df_farming.config.light_kills_fungus then
	local kill_if_sunlit = function(pos, node)
		if not node then
			node = minetest.get_node(pos)
		end
		local node_def = minetest.registered_nodes[node.name]
		local light_sensitive_fungus_level = node_def.groups.light_sensitive_fungus

		-- This should never be the case, but I've received a report of it happening anyway in the ABM so guarding against it.
		if not light_sensitive_fungus_level then return false end

		local dead_node = node_def._dfcaverns_dead_node or "df_farming:dead_fungus"
		-- 11 is the value adjacent to a torch
		local light_level = minetest.get_node_light(pos, 0.5) -- check at 0.5 to get how bright it would be here at noon,
			-- prevents fungus from growing on the surface world by happenstance
		if light_level and light_level > light_sensitive_fungus_level then
			minetest.set_node(pos, {name=dead_node, param2 = node.param2})
			return true
		end
		return false
	end

	df_farming.kill_if_sunlit = kill_if_sunlit

	minetest.register_abm({
		label = "df_farming:kill_light_sensitive_fungus",
		nodenames = {"group:light_sensitive_fungus"},
		catch_up = true,
		interval = 30,
		chance = 5,
		action = function(pos, node)
			kill_if_sunlit(pos, node)
		end
	})
end


code:
local S = minetest.get_translator(minetest.get_current_modname())

local displace_x = 0.125
local displace_z = 0.125

local plump_helmet_grow_time = df_farming.config.plant_growth_time * df_farming.config.plump_helmet_delay_multiplier / 4

local function copy_pointed_thing(pointed_thing)
	return {
		type  = pointed_thing.type,
		above = pointed_thing.above and vector.copy(pointed_thing.above),
		under = pointed_thing.under and vector.copy(pointed_thing.under),
		ref   = pointed_thing.ref,
	}
end

local plump_helmet_on_place =  function(itemstack, placer, pointed_thing, plantname)
	local pt = pointed_thing
	-- check if pointing at a node
	if not pt then
		return itemstack
	end
	if pt.type ~= "node" then
		return itemstack
	end

	local under = minetest.get_node(pt.under)
	local above = minetest.get_node(pt.above)

	if minetest.is_protected(pt.under, placer:get_player_name()) then
		minetest.record_protection_violation(pt.under, placer:get_player_name())
		return
	end
	if minetest.is_protected(pt.above, placer:get_player_name()) then
		minetest.record_protection_violation(pt.above, placer:get_player_name())
		return
	end

	-- return if any of the nodes is not registered
	if not minetest.registered_nodes[under.name] then
		return itemstack
	end
	if not minetest.registered_nodes[above.name] then
		return itemstack
	end

	-- check if pointing at the top of the node
	if pt.above.y ~= pt.under.y+1 then
		return itemstack
	end

	-- check if you can replace the node above the pointed node
	if not minetest.registered_nodes[above.name].buildable_to then
		return itemstack
	end

	-- add the node and remove 1 item from the itemstack
	local new_param2 = math.random(0,3)
	local newnode= {name = plantname, param2 = new_param2, param1=0}
	local oldnode= minetest.get_node(pt.above)
	minetest.add_node(pt.above, newnode)

	local growth_permitted_function = df_farming.growth_permitted["df_farming:plump_helmet_spawn"] -- use the same permitted function for all plump helmets
	if not growth_permitted_function or growth_permitted_function(pt.above) then
		df_farming.plant_timer(pt.above, plantname)
	end

	-- Run script hook
	local take_item = true
	for _, callback in ipairs(core.registered_on_placenodes) do
		-- Deepcopy pos, node and pointed_thing because callback can modify them
		local place_to_copy = vector.copy(pt.above)
		local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
		local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
		local pointed_thing_copy = copy_pointed_thing(pointed_thing)
		if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then
			take_item = false
		end
	end

	if not minetest.is_creative_enabled(placer:get_player_name()) then
		itemstack:take_item()
	end
	return itemstack
end

minetest.register_node("df_farming:plump_helmet_spawn", {
	description = S("Plump Helmet Spawn"),
	_doc_items_longdesc = df_farming.doc.plump_helmet_desc,
	_doc_items_usagehelp = df_farming.doc.plump_helmet_usage,
	tiles = {
		"dfcaverns_plump_helmet_cap.png",
	},
	groups = {snappy = 3, plant = 1, attached_node = 1, light_sensitive_fungus = 11, dfcaverns_cookable = 1, digtron_on_place=1, destroy_by_lava_flow=1,dig_by_piston=1, handy=1, hoey=1},
	_dfcaverns_next_stage = "df_farming:plump_helmet_1",
	_dfcaverns_next_stage_time = plump_helmet_grow_time,
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	walkable = false,
	is_ground_content = false,
	floodable = true,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.0625 + displace_x, -0.5, -0.125 + displace_z, 0.125 + displace_x, -0.375, 0.0625 + displace_z},
		}
	},
	_mcl_blast_resistance = 0.2,
	_mcl_hardness = 0.2,

	on_place = function(itemstack, placer, pointed_thing)
		return plump_helmet_on_place(itemstack, placer, pointed_thing, "df_farming:plump_helmet_spawn")
	end,

	on_timer = function(pos, elapsed)
		df_farming.grow_underground_plant(pos, "df_farming:plump_helmet_spawn", elapsed)
	end,

	on_destruct = function(pos)
		minetest.get_node_timer(pos):stop()
	end,
})

local plump_helmet_groups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, light_sensitive_fungus = 11, dfcaverns_cookable = 1, plump_helmet = 1, digtron_on_place=1, fire_encouragement=30,fire_flammability=100,destroy_by_lava_flow=1,dig_by_piston=1,compostability=65}
local get_plump_helmet_groups = function(eatable)
	local ret = {}
	for key, val in pairs(plump_helmet_groups) do
		ret[key]=val
	end
	ret.eatable = eatable
	ret.food = eatable
	return ret
end

minetest.register_node("df_farming:plump_helmet_1", {
	description = S("Plump Helmet"),
	_doc_items_longdesc = df_farming.doc.plump_helmet_desc,
	_doc_items_usagehelp = df_farming.doc.plump_helmet_usage,
	tiles = {
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png^[lowpart:5:dfcaverns_plump_helmet_stem.png",
	},
	groups = get_plump_helmet_groups(1),
	_dfcaverns_next_stage = "df_farming:plump_helmet_2",
	_dfcaverns_next_stage_time = plump_helmet_grow_time,
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	is_ground_content = false,
	sounds = df_dependencies.sound_leaves(),
	sound = {eat = {name = "df_farming_gummy_chew", gain = 1.0}},
	walkable = false,
	floodable = true,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.0625 + displace_x, -0.5, -0.125 + displace_z, 0.125 + displace_x, -0.25, 0.0625 + displace_z},      -- stalk
			{-0.125 + displace_x, -0.4375, -0.1875 + displace_z, 0.1875 + displace_x, -0.3125, 0.125 + displace_z}, -- cap
		}
	},
	_mcl_blast_resistance = 0.3,
	_mcl_hardness = 0.3,

	on_place = function(itemstack, placer, pointed_thing)
		return plump_helmet_on_place(itemstack, placer, pointed_thing, "df_farming:plump_helmet_1")
	end,

	on_use = minetest.item_eat(1),
	_hunger_ng = {satiates = 1},
	_mcl_saturation = 0.5,

	on_timer = function(pos, elapsed)
		df_farming.grow_underground_plant(pos, "df_farming:plump_helmet_1", elapsed)
	end,
})

minetest.register_node("df_farming:plump_helmet_2", {
	description = S("Plump Helmet"),
	_doc_items_longdesc = df_farming.doc.plump_helmet_desc,
	_doc_items_usagehelp = df_farming.doc.plump_helmet_usage,
	tiles = {
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png^[lowpart:15:dfcaverns_plump_helmet_stem.png",
	},
	groups = get_plump_helmet_groups(2),
	_dfcaverns_next_stage = "df_farming:plump_helmet_3",
	_dfcaverns_next_stage_time = plump_helmet_grow_time,
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	sounds = df_dependencies.sound_leaves(),
	sound = {eat = {name = "df_farming_gummy_chew", gain = 1.0}},
	walkable = false,
	is_ground_content = false,
	floodable = true,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.0625 + displace_x, -0.5, -0.125 + displace_z, 0.125 + displace_x, 0, 0.0625 + displace_z},  -- stalk
			{-0.125 + displace_x, -0.3125, -0.1875 + displace_z, 0.1875 + displace_x, -0.0625, 0.125 + displace_z},  -- cap
		}
	},
	_mcl_blast_resistance = 0.4,
	_mcl_hardness = 0.4,

	on_place = function(itemstack, placer, pointed_thing)
		return plump_helmet_on_place(itemstack, placer, pointed_thing, "df_farming:plump_helmet_2")
	end,

	on_use = minetest.item_eat(2),
	_hunger_ng = {satiates = 2},
	_mcl_saturation = 0.7,

	on_timer = function(pos, elapsed)
		df_farming.grow_underground_plant(pos, "df_farming:plump_helmet_2", elapsed)
	end,
})

minetest.register_node("df_farming:plump_helmet_3", {
	description = S("Plump Helmet"),
	_doc_items_longdesc = df_farming.doc.plump_helmet_desc,
	_doc_items_usagehelp = df_farming.doc.plump_helmet_usage,
	tiles = {
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png^[lowpart:35:dfcaverns_plump_helmet_stem.png",
	},
	groups = get_plump_helmet_groups(3),
	_dfcaverns_next_stage = "df_farming:plump_helmet_4",
	_dfcaverns_next_stage_time = plump_helmet_grow_time,
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	sounds = df_dependencies.sound_leaves(),
	sound = {eat = {name = "df_farming_gummy_chew", gain = 1.0}},
	walkable = false,
	is_ground_content = false,
	floodable = true,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.125 + displace_x, -0.5, -0.1875 + displace_z, 0.1875 + displace_x, 0.25, 0.125 + displace_z}, -- stalk
			{-0.1875 + displace_x, -0.125, -0.25 + displace_z, 0.25 + displace_x, 0.1875, 0.1875 + displace_z}, -- cap
		}
	},
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.5,

	on_place = function(itemstack, placer, pointed_thing)
		return plump_helmet_on_place(itemstack, placer, pointed_thing, "df_farming:plump_helmet_3")
	end,

	on_use = minetest.item_eat(3),
	_hunger_ng = {satiates = 3},
	_mcl_saturation = 0.9,

	on_timer = function(pos, elapsed)
		df_farming.grow_underground_plant(pos, "df_farming:plump_helmet_3", elapsed)
	end,
})

minetest.register_node("df_farming:plump_helmet_4", {
	description = S("Plump Helmet"),
	_doc_items_longdesc = df_farming.doc.plump_helmet_desc,
	_doc_items_usagehelp = df_farming.doc.plump_helmet_usage,
	tiles = {
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png^[lowpart:40:dfcaverns_plump_helmet_stem.png",
	},
	groups = get_plump_helmet_groups(4),
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	sounds = df_dependencies.sound_leaves(),
	sound = {eat = {name = "df_farming_gummy_chew", gain = 1.0}},
	walkable = false,
	is_ground_content = false,
	floodable = false, -- I figure full grown plump helmets are sturdy enough to survive inundation
	node_box = {
		type = "fixed",
		fixed = {
			{-0.125 + displace_x, -0.5, -0.1875 + displace_z, 0.1875 + displace_x, 0.375, 0.125 + displace_z}, -- stalk
			{-0.25 + displace_x, -0.0625, -0.3125 + displace_z, 0.3125 + displace_x, 0.25, 0.25 + displace_z}, -- cap
			{-0.1875 + displace_x, 0.25, -0.25 + displace_z, 0.25 + displace_x, 0.3125, 0.1875 + displace_z}, -- cap rounding
		}
	},
	_mcl_blast_resistance = 0.6,
	_mcl_hardness = 0.6,

	drop = {
		max_items = 4,
		items = {
			{
				items = {'df_farming:plump_helmet_4_picked'},
				rarity = 1,
			},
			{
				items = {'df_farming:plump_helmet_spawn'},
				rarity = 1,
			},
			{
				items = {'df_farming:plump_helmet_spawn'},
				rarity = 2,
			},
			{
				items = {'df_farming:plump_helmet_spawn'},
				rarity = 2,
			},
		},
	},
	on_place = function(itemstack, placer, pointed_thing)
		return plump_helmet_on_place(itemstack, placer, pointed_thing, "df_farming:plump_helmet_4")
	end,

	on_use = minetest.item_eat(4),
	_hunger_ng = {satiates = 4},
	_mcl_saturation = 1,
})

local picked_groups = {}
for key, val in pairs(plump_helmet_groups) do
	picked_groups[key]=val
	picked_groups.eatable=4
	picked_groups.food=4
end
picked_groups.not_in_creative_inventory = nil
-- Need a separate picked type to prevent it from giving infinite spawn by just placing and re-harvesting
minetest.register_node("df_farming:plump_helmet_4_picked", {
	description = S("Plump Helmet"),
	_doc_items_longdesc = df_farming.doc.plump_helmet_desc,
	_doc_items_usagehelp = df_farming.doc.plump_helmet_usage,
	tiles = {
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png",
		"dfcaverns_plump_helmet_cap.png^[lowpart:40:dfcaverns_plump_helmet_stem.png",
	},
	groups = picked_groups,
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	sounds = df_dependencies.sound_leaves(),
	sound = {eat = {name = "df_farming_gummy_chew", gain = 1.0}},
	walkable = false,
	is_ground_content = false,
	floodable = false,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.125 + displace_x, -0.5, -0.1875 + displace_z, 0.1875 + displace_x, 0.375, 0.125 + displace_z}, -- stalk
			{-0.25 + displace_x, -0.0625, -0.3125 + displace_z, 0.3125 + displace_x, 0.25, 0.25 + displace_z}, -- cap
			{-0.1875 + displace_x, 0.25, -0.25 + displace_z, 0.25 + displace_x, 0.3125, 0.1875 + displace_z}, -- cap rounding
		}
	},
	_mcl_blast_resistance = 0.6,
	_mcl_hardness = 0.6,

	on_place = function(itemstack, placer, pointed_thing)
		return plump_helmet_on_place(itemstack, placer, pointed_thing, "df_farming:plump_helmet_4_picked")
	end,

	on_use = minetest.item_eat(4),
	_hunger_ng = {satiates = 4},
	_mcl_saturation = 1,
})

local place_list = {
	minetest.get_content_id("df_farming:plump_helmet_spawn"),
	minetest.get_content_id("df_farming:plump_helmet_1"),
	minetest.get_content_id("df_farming:plump_helmet_2"),
	minetest.get_content_id("df_farming:plump_helmet_3"),
	minetest.get_content_id("df_farming:plump_helmet_4"),
}
-- doesn't set the timer running, so plants placed by this method won't grow
df_farming.spawn_plump_helmet_vm = function(vi, area, data, param2_data)
	data[vi] = place_list[math.random(1,5)]
	param2_data[vi] = math.random(1,4)-1
end

minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:plump_helmet_spawn",
	burntime = 1
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:plump_helmet_1",
	burntime = 1
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:plump_helmet_2",
	burntime = 2
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:plump_helmet_3",
	burntime = 3
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:plump_helmet_4",
	burntime = 4
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:plump_helmet_4_picked",
	burntime = 4
})

repo_name: korkut/MeseCraft

license: mit


code:
local S = minetest.get_translator(minetest.get_current_modname())

local quarry_grow_time = df_farming.config.plant_growth_time * df_farming.config.quarry_bush_delay_multiplier / 5

local register_quarry_bush = function(number)
	local name = "df_farming:quarry_bush_"..tostring(number)
	local def = {
		description = S("Quarry Bush"),
		_doc_items_longdesc = df_farming.doc.quarry_bush_desc,
		_doc_items_usagehelp = df_farming.doc.quarry_bush_usage,
		drawtype = "plantlike",
		paramtype2 = "meshoptions",
		place_param2 = 4,
		tiles = {"dfcaverns_quarry_bush_"..tostring(number)..".png"},
		inventory_image = "dfcaverns_quarry_bush_"..tostring(number)..".png",
		paramtype = "light",
		walkable = false,
		buildable_to = true,
		is_ground_content = false,
		floodable = true,
		groups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, light_sensitive_fungus = 11, fire_encouragement=60,fire_flammability=100, compostability=50, handy=1,shearsy=1,hoey=1, destroy_by_lava_flow=1,dig_by_piston=1},
		sounds = df_dependencies.sound_leaves(),
        selection_box = {
            type = "fixed",
            fixed = {
                {-8/16, -8/16, -8/16, 8/16, -8/16 + (16/5)*number/16, 8/16},
            },
        },
		_mcl_blast_resistance = 0.2,
		_mcl_hardness = 0.2,

		on_timer = function(pos, elapsed)
			df_farming.grow_underground_plant(pos, name, elapsed)
		end,

		drop = {
			max_items = 2,
			items = {
				{
					items = {'df_farming:quarry_bush_seed 2', 'df_farming:quarry_bush_leaves 2'},
					rarity = 6-number,
				},
				{
					items = {'df_farming:quarry_bush_seed 1', 'df_farming:quarry_bush_leaves'},
					rarity = 6-number,
				},
				{
					items = {'df_farming:quarry_bush_seed'},
					rarity = 6-number,
				},
			},
		},
	}

	if number < 5 then
		def._dfcaverns_next_stage_time = quarry_grow_time
		def._dfcaverns_next_stage = "df_farming:quarry_bush_"..tostring(number+1)
	end

	minetest.register_node(name, def)
end

for i = 1,5 do
	register_quarry_bush(i)
end

local place_list = {
	minetest.get_content_id("df_farming:quarry_bush_1"),
	minetest.get_content_id("df_farming:quarry_bush_2"),
	minetest.get_content_id("df_farming:quarry_bush_3"),
	minetest.get_content_id("df_farming:quarry_bush_4"),
	minetest.get_content_id("df_farming:quarry_bush_5"),
}
-- doesn't set the timer running, so plants placed by this method won't grow
df_farming.spawn_quarry_bush_vm = function(vi, area, data, param2_data)
	data[vi] = place_list[math.random(1,5)]
	param2_data[vi] = 4
end

df_farming.register_seed(
	"quarry_bush_seed",
	S("Rock Nuts"),
	"dfcaverns_rock_nuts.png",
	"df_farming:quarry_bush_1",
	quarry_grow_time,
	df_farming.doc.quarry_bush_desc,
	df_farming.doc.quarry_bush_usage
)

minetest.register_craftitem("df_farming:quarry_bush_leaves", {
	description = S("Quarry Bush Leaves"),
	_doc_items_longdesc = df_farming.doc.quarry_bush_leaves_desc,
	_doc_items_usagehelp = df_farming.doc.quarry_bush_leaves_usage,
	inventory_image = "dfcaverns_quarry_bush_leaves.png",
	groups = {dfcaverns_cookable = 1},
	stack_max = 99,
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:quarry_bush_leaves",
	burntime = 4
})


code:
dfcaverns_plant_growth_time (Base plant growth timer interval) int 3600
dfcaverns_cave_wheat_delay_multiplier (cave_wheat growth delay multiplier) float 1
dfcaverns_dimple_cup_delay_multiplier (dimple_cup growth delay multiplier) float 3
dfcaverns_pig_tail_delay_multiplier (pig_tail growth delay multiplier) float 1
dfcaverns_plump_helmet_delay_multiplier (plump_helmet growth delay multiplier) float 3
dfcaverns_quarry_bush_delay_multiplier (quarry_bush growth delay multiplier) float 2
dfcaverns_sweet_pod_delay_multiplier (sweet_pod growth delay multiplier) float 2
dfcaverns_light_kills_fungus (Light kills fungus) bool true


code:
local S = minetest.get_translator(minetest.get_current_modname())

local sweet_pod_grow_time = df_farming.config.plant_growth_time * df_farming.config.sweet_pod_delay_multiplier / 6

local syrup_sound = df_dependencies.sound_water()
if minetest.get_modpath("oil") then
	syrup_sound.footstep = {name = "oil_oil_footstep", gain = 0.2}
end

local register_sweet_pod = function(number)
	local name = "df_farming:sweet_pod_"..tostring(number)
	local def = {
		description = S("Sweet Pod"),
		_doc_items_longdesc = df_farming.doc.sweet_pod_desc,
		_doc_items_usagehelp = df_farming.doc.sweet_pod_usage,
		drawtype = "plantlike",
		tiles = {"dfcaverns_sweet_pod_"..tostring(number)..".png"},
		inventory_image = "dfcaverns_sweet_pod_"..tostring(number)..".png",
		paramtype = "light",
		walkable = false,
		is_ground_content = false,
		buildable_to = true,
		floodable = true,
		groups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, light_sensitive_fungus = 11, fire_encouragement=60,fire_flammability=100, compostability=70, handy=1,shearsy=1,hoey=1, destroy_by_lava_flow=1,dig_by_piston=1},
		sounds = df_dependencies.sound_leaves(),
        selection_box = {
            type = "fixed",
            fixed = {
                {-8/16, -8/16, -8/16, 8/16, -8/16 + (16/6)*number/16, 8/16},
            },
        },
		_mcl_blast_resistance = 0.2,
		_mcl_hardness = 0.2,

		on_timer = function(pos, elapsed)
			df_farming.grow_underground_plant(pos, name, elapsed)
		end,

		drop = {
			max_items = 2,
			items = {
				{
					items = {'df_farming:sweet_pod_seed 2', 'df_farming:sweet_pods 2'},
					rarity = 7-number,
				},
				{
					items = {'df_farming:sweet_pod_seed', 'df_farming:sweet_pods'},
					rarity = 7-number,
				},
				{
					items = {'df_farming:sweet_pod_seed'},
					rarity = 7-number,
				},
			},
		},
	}

	if number < 6 then
		def._dfcaverns_next_stage = "df_farming:sweet_pod_"..tostring(number+1)
		def._dfcaverns_next_stage_time = sweet_pod_grow_time
	end

	minetest.register_node(name, def)
end

for i = 1,6 do
	register_sweet_pod(i)
end

local place_list = {
	minetest.get_content_id("df_farming:sweet_pod_1"),
	minetest.get_content_id("df_farming:sweet_pod_2"),
	minetest.get_content_id("df_farming:sweet_pod_3"),
	minetest.get_content_id("df_farming:sweet_pod_4"),
	minetest.get_content_id("df_farming:sweet_pod_5"),
	minetest.get_content_id("df_farming:sweet_pod_6"),
}
-- doesn't set the timer running, so plants placed by this method won't grow
df_farming.spawn_sweet_pod_vm = function(vi, area, data, param2_data)
	data[vi] = place_list[math.random(1,8)]
	param2_data[vi] = 0
end

df_farming.register_seed(
	"sweet_pod_seed",
	S("Sweet Pod Spores"),
	"dfcaverns_sweet_pod_seed.png",
	"df_farming:sweet_pod_1",
	sweet_pod_grow_time,
	df_farming.doc.sweet_pod_desc,
	df_farming.doc.sweet_pod_usage)

minetest.register_craftitem("df_farming:sweet_pods", {
	description = S("Sweet Pods"),
	_doc_items_longdesc = df_farming.doc.sweet_pod_desc,
	_doc_items_usagehelp = df_farming.doc.sweet_pod_usage,
	inventory_image = "dfcaverns_sweet_pods.png",
	stack_max = 99,
})
minetest.register_craft({
	type = "fuel",
	recipe = "df_farming:sweet_pods",
	burntime = 4
})

---------------------------------------------
-- Sugar

minetest.register_craftitem("df_farming:sugar", {
	description = S("Sweet Pod Sugar"),
	_doc_items_longdesc = df_farming.doc.sweet_pod_sugar_desc,
	_doc_items_usagehelp = df_farming.doc.sweet_pod_sugar_usage,
	inventory_image = "dfcaverns_sugar.png",
	groups = {dfcaverns_cookable = 1, sugar = 1},
})

local recipe_registered = false

if minetest.get_modpath("cottages") then
	cottages.handmill_product["df_farming:sweet_pods"] = "df_farming:sugar";
	recipe_registered = true
end

if minetest.registered_items[df_dependencies.node_name_mortar_pestle] ~= nil then
	minetest.register_craft({
		type = "shapeless",
		output = "df_farming:sugar",
		recipe = {
			"df_farming:sweet_pods", df_dependencies.node_name_mortar_pestle
		},
		replacements = {{"group:food_mortar_pestle", df_dependencies.node_name_mortar_pestle}},
	})
	recipe_registered = true
end

if not recipe_registered then
minetest.register_craft({
	type = "cooking",
	cooktime = 3,
	output = "df_farming:sugar",
	recipe = "df_farming:sweet_pods",
})
end

----------------------------------------------
-- Syrup

if df_dependencies.bucket_register_liquid then
	minetest.register_node("df_farming:dwarven_syrup_source", {
		description = S("Dwarven Syrup Source"),
		_doc_items_longdesc = df_farming.doc.sweet_pod_syrup_desc,
		_doc_items_usagehelp = df_farming.doc.sweet_pod_syrup_usage,
		drawtype = "liquid",
		tiles = {
			{
				name = "dfcaverns_dwarven_syrup_source_animated.png",
				animation = {
					type = "vertical_frames",
					aspect_w = 16,
					aspect_h = 16,
					length = 2.0,
				},
			},
		},
		special_tiles = {
			{
				name = "dfcaverns_dwarven_syrup_source_animated.png",
				animation = {
					type = "vertical_frames",
					aspect_w = 16,
					aspect_h = 16,
					length = 2.0,
				},
				backface_culling = false,
			},
		},
		alpha = 204,
		paramtype = "light",
		walkable = false,
		pointable = false,
		diggable = false,
		buildable_to = true,
		is_ground_content = false,
		drop = "",
		drowning = 1,
		liquidtype = "source",
		liquid_alternative_flowing = "df_farming:dwarven_syrup_flowing",
		liquid_alternative_source = "df_farming:dwarven_syrup_source",
		liquid_viscosity = 7,
		liquid_renewable = false,
		liquid_range = 2,
		post_effect_color = {a = 204, r = 179, g = 131, b = 88},
		groups = {liquid = 1, flammable = -1, dig_by_piston=1, fire_encouragement=5},
		sounds = syrup_sound,
		_mcl_blast_resistance      = 100,
		_mcl_hardness              = -1,
	})

	minetest.register_node("df_farming:dwarven_syrup_flowing", {
		description = S("Flowing Dwarven Syrup"),
		_doc_items_longdesc = df_farming.doc.sweet_pod_syrup_desc,
		_doc_items_usagehelp = df_farming.doc.sweet_pod_syrup_usage,
		drawtype = "flowingliquid",
		tiles = {"dfcaverns_dwarven_syrup.png"},
		special_tiles = {
			{
				name = "dfcaverns_dwarven_syrup_flowing_animated.png",
				backface_culling = false,
				animation = {
					type = "vertical_frames",
					aspect_w = 16,
					aspect_h = 16,
					length = 0.8,
				},
			},
			{
				name = "dfcaverns_dwarven_syrup_flowing_animated.png",
				backface_culling = true,
				animation = {
					type = "vertical_frames",
					aspect_w = 16,
					aspect_h = 16,
					length = 0.8,
				},
			},
		},
		alpha = 204,
		paramtype = "light",
		paramtype2 = "flowingliquid",
		walkable = false,
		pointable = false,
		diggable = false,
		buildable_to = true,
		is_ground_content = false,
		drop = "",
		drowning = 1,
		liquidtype = "flowing",
		liquid_alternative_flowing = "df_farming:dwarven_syrup_flowing",
		liquid_alternative_source = "df_farming:dwarven_syrup_source",
		liquid_viscosity = 7,
		liquid_renewable = false,
		liquid_range = 2,
		post_effect_color = {a = 204, r = 179, g = 131, b = 88},
		groups = {liquid = 1, flammable = -1, not_in_creative_inventory = 1, dig_by_piston=1, fire_encouragement = 5},
		sounds = syrup_sound,
		_mcl_blast_resistance      = 100,
		_mcl_hardness              = -1,
	})

	df_dependencies.bucket_register_liquid(
		"df_farming:dwarven_syrup_source",
		"df_farming:dwarven_syrup_flowing",
		"df_farming:dwarven_syrup_bucket",
		"dfcaverns_bucket_dwarven_syrup.png",
		S("Dwarven Syrup Bucket")
	)

	if minetest.get_modpath("crafting") then
		simplecrafting_lib.register("furnace", {
			input = {
				[df_dependencies.node_name_bucket_empty] = 1,
				["df_farming:sugar"] = 3,
				["simplecrafting_lib:heat"] = 5,
			},
			output = "df_farming:dwarven_syrup_bucket",
		})
	else
		minetest.register_craft({
			type = "shapeless",
			output = "df_farming:dwarven_syrup_bucket",
			recipe = {df_dependencies.node_name_bucket_empty, "df_farming:sugar", "df_farming:sugar", "df_farming:sugar"},
		})
	end

	if minetest.get_modpath("dynamic_liquid") then
		dynamic_liquid.liquid_abm("df_farming:dwarven_syrup_source", "df_farming:dwarven_syrup_flowing", 5)
	end
end


code:
-- These used to be defined in subterrane, but now dfcaverns handles it.
if not minetest.registered_nodes["subterrane:wet_flowstone"] then
	minetest.register_alias("subterrane:dry_stal_1", "df_mapitems:dry_stal_1")
	minetest.register_alias("subterrane:dry_stal_2", "df_mapitems:dry_stal_2")
	minetest.register_alias("subterrane:dry_stal_3", "df_mapitems:dry_stal_3")
	minetest.register_alias("subterrane:dry_stal_4", "df_mapitems:dry_stal_4")
	minetest.register_alias("subterrane:wet_stal_1", "df_mapitems:wet_stal_1")
	minetest.register_alias("subterrane:wet_stal_2", "df_mapitems:wet_stal_2")
	minetest.register_alias("subterrane:wet_stal_3", "df_mapitems:wet_stal_3")
	minetest.register_alias("subterrane:wet_stal_4", "df_mapitems:wet_stal_4")
	minetest.register_alias("subterrane:wet_flowstone", "df_mapitems:wet_flowstone")
	minetest.register_alias("subterrane:dry_flowstone", "df_mapitems:dry_flowstone")
end

minetest.register_alias("dfcaverns:cave_coral_3"                 , "df_mapitems:cave_coral_3"                 )
minetest.register_alias("dfcaverns:cave_coral_2"                 , "df_mapitems:cave_coral_2"                 )
minetest.register_alias("dfcaverns:cave_coral_1"                 , "df_mapitems:cave_coral_1"                 )
minetest.register_alias("dfcaverns:dry_stal_1"                   , "df_mapitems:dry_stal_1"                   )
minetest.register_alias("dfcaverns:dry_stal_2"                   , "df_mapitems:dry_stal_2"                   )
minetest.register_alias("dfcaverns:dry_stal_3"                   , "df_mapitems:dry_stal_3"                   )
minetest.register_alias("dfcaverns:dry_stal_4"                   , "df_mapitems:dry_stal_4"                   )
minetest.register_alias("dfcaverns:wet_stal_1"                   , "df_mapitems:wet_stal_1"                   )
minetest.register_alias("dfcaverns:wet_stal_2"                   , "df_mapitems:wet_stal_2"                   )
minetest.register_alias("dfcaverns:wet_stal_3"                   , "df_mapitems:wet_stal_3"                   )
minetest.register_alias("dfcaverns:wet_stal_4"                   , "df_mapitems:wet_stal_4"                   )
minetest.register_alias("dfcaverns:wet_flowstone"                , "df_mapitems:wet_flowstone"                )
minetest.register_alias("dfcaverns:dry_flowstone"                , "df_mapitems:dry_flowstone"                )
minetest.register_alias("dfcaverns:icicle_1"                     , "df_mapitems:icicle_1"                     )
minetest.register_alias("dfcaverns:icicle_2"                     , "df_mapitems:icicle_2"                     )
minetest.register_alias("dfcaverns:icicle_3"                     , "df_mapitems:icicle_3"                     )
minetest.register_alias("dfcaverns:icicle_4"                     , "df_mapitems:icicle_4"                     )
minetest.register_alias("dfcaverns:glow_mese"                    , "df_mapitems:glow_mese"                    )
minetest.register_alias("dfcaverns:glow_ruby_ore"                , "df_mapitems:glow_ruby_ore"                )
minetest.register_alias("dfcaverns:big_crystal"                  , "df_mapitems:big_crystal"                  )
minetest.register_alias("dfcaverns:med_crystal"                  , "df_mapitems:med_crystal"                  )
minetest.register_alias("dfcaverns:big_crystal_30"               , "df_mapitems:big_crystal_30"               )
minetest.register_alias("dfcaverns:med_crystal_30"               , "df_mapitems:med_crystal_30"               )
minetest.register_alias("dfcaverns:big_crystal_30_45"            , "df_mapitems:big_crystal_30_45"            )
minetest.register_alias("dfcaverns:med_crystal_30_45"            , "df_mapitems:med_crystal_30_45"            )
minetest.register_alias("dfcaverns:glow_worm"                    , "df_mapitems:glow_worm"                    )
minetest.register_alias("dfcaverns:dirt_with_cave_moss"          , "df_mapitems:dirt_with_cave_moss"          )
minetest.register_alias("dfcaverns:cobble_with_floor_fungus"     , "df_mapitems:cobble_with_floor_fungus"     )
minetest.register_alias("dfcaverns:cobble_with_floor_fungus_fine", "df_mapitems:cobble_with_floor_fungus_fine")
minetest.register_alias("dfcaverns:snareweed"                    , "df_mapitems:snareweed"                    )


code:
local S = minetest.get_translator(minetest.get_current_modname())

minetest.register_node("df_mapitems:castle_coral", {
	description = S("Castle Coral"),
	tiles = {
		"dfcaverns_castle_coral_gradient.png",
		"dfcaverns_castle_coral.png",
		"dfcaverns_castle_coral.png",
		"dfcaverns_castle_coral.png^[multiply:#888888",
	},
	_doc_items_longdesc = df_mapitems.doc.castle_coral_desc,
	_doc_items_usagehelp = df_mapitems.doc.castle_coral_usage,
	drawtype = "mesh",
	is_ground_content = false,
	light_source = 2,
	mesh = "octagonal_coral.obj",
	drop = "df_mapitems:castle_coral_skeleton",
	paramtype = "light",
	groups = {cracky=2, pickaxey = 1, building_block = 1, coral=1, coral_block=1},
	sounds = df_dependencies.sound_stone(),
	_mcl_hardness = 1.5,
	_mcl_blast_resistance = 6,
})

minetest.register_node("df_mapitems:castle_coral_skeleton", {
	description = S("Castle Coral Skeleton"),
	_doc_items_longdesc = df_mapitems.doc.castle_coral_desc,
	_doc_items_usagehelp = df_mapitems.doc.castle_coral_usage,
	tiles = {
		df_dependencies.texture_coral_skeleton
	},
	drawtype = "mesh",
	mesh = "octagonal_coral.obj",
	paramtype = "light",
	is_ground_content = false,
	groups = {cracky = 3,pickaxey = 1, building_block = 1, coral=2, coral_block=1},
	sounds = df_dependencies.sound_stone(),
	_mcl_hardness = 1.5,
	_mcl_blast_resistance = 6,
})

local c_coral = minetest.get_content_id("df_mapitems:castle_coral")
local c_coral_skeleton = minetest.get_content_id("df_mapitems:castle_coral_skeleton")

local c_stone = minetest.get_content_id(df_dependencies.node_name_stone)
local c_water = minetest.get_content_id(df_dependencies.node_name_water_source)

df_mapitems.spawn_castle_coral = function(area, data, vi, iterations)
	local run = math.random(2,4)
	local index = vi
	local zstride = area.zstride
	local ystride = area.ystride
	while run > 0 do
		-- TODO should this be checking for not-water instead of stone?
		if math.random() > 0.95 or data[index] == c_stone or not area:containsi(index) then return end
		data[index] = c_coral
		if iterations > 2 then
			data[index + 1] = c_coral
			data[index - 1] = c_coral
			data[index + zstride] = c_coral
			data[index - zstride] = c_coral
		end
		if iterations > 3 then
			data[index + 2] = c_coral
			data[index - 2] = c_coral
			data[index + zstride * 2] = c_coral
			data[index - zstride * 2] = c_coral
			data[index + 1 + zstride] = c_coral
			data[index - 1 + zstride] = c_coral
			data[index + 1 - zstride] = c_coral
			data[index - 1 - zstride] = c_coral
		end
		index = index + ystride
		run = run - 1
	end

	local newiterations = iterations - 1
	if newiterations == 0 then return end

	if math.random() > 0.5 then
		df_mapitems.spawn_castle_coral(area, data, index + 1 - ystride, newiterations)
		df_mapitems.spawn_castle_coral(area, data, index - 1 - ystride, newiterations)
	else
		df_mapitems.spawn_castle_coral(area, data, index + zstride - ystride, newiterations)
		df_mapitems.spawn_castle_coral(area, data, index - zstride - ystride, newiterations)
	end
end

df_mapitems.spawn_coral_pile = function(area, data, vi, radius)
	local pos = area:position(vi)
	for li in area:iterp(vector.add(pos, -radius), vector.add(pos, radius)) do
		local adjacent = li + area.ystride
		local node_type = data[li]
		if math.random() < 0.2  and not mapgen_helper.buildable_to(node_type) and data[adjacent] == c_water then
			data[adjacent] = c_coral_skeleton
		end
	end
end


code:
local S = minetest.get_translator(minetest.get_current_modname())

local water_source = df_dependencies.node_name_water_source
local coral_skeleton = df_dependencies.node_name_coral_skeleton

minetest.register_node("df_mapitems:cave_coral_3", {
	description = S("Cave Coral"),
	_doc_items_longdesc = df_mapitems.doc.cave_coral_desc,
	_doc_items_usagehelp = df_mapitems.doc.cave_coral_usage,
	tiles = {"dfcaverns_cave_coral_end.png", "dfcaverns_cave_coral_end.png", "dfcaverns_cave_coral.png"},
	drop = coral_skeleton,
	light_source = 3,
	paramtype2 = "facedir",
	is_ground_content = false,
	groups = {cracky = 3, dfcaverns_cave_coral = 1, pickaxey = 1, building_block = 1, coral=1, coral_block=1},
	sounds = df_dependencies.sound_stone(),
	on_timer = function(pos)
		if minetest.find_node_near(pos, 1, {water_source}) == nil then
			minetest.set_node(pos, {name=coral_skeleton})
		end
	end,
	_mcl_hardness = 1.5,
	_mcl_blast_resistance = 6,
})

minetest.register_node("df_mapitems:cave_coral_2", {
	description = S("Cave Coral"),
	_doc_items_longdesc = df_mapitems.doc.cave_coral_desc,
	_doc_items_usagehelp = df_mapitems.doc.cave_coral_usage,
	tiles = {"dfcaverns_cave_coral_end.png", "dfcaverns_cave_coral_end.png", "dfcaverns_cave_coral.png"},
	drop = coral_skeleton,
	light_source = 2,
	paramtype2 = "facedir",
	is_ground_content = false,
	groups = {cracky = 3, dfcaverns_cave_coral = 1, pickaxey = 1, building_block = 1, coral=1, coral_block=1},
	sounds = df_dependencies.sound_stone(),
	on_timer = function(pos)
		if minetest.find_node_near(pos, 1, {water_source}) == nil then
			minetest.set_node(pos, {name=coral_skeleton})
		end
	end,
	_mcl_hardness = 1.5,
	_mcl_blast_resistance = 6,
})

minetest.register_node("df_mapitems:cave_coral_1", {
	description = S("Cave Coral"),
	_doc_items_longdesc = df_mapitems.doc.cave_coral_desc,
	_doc_items_usagehelp = df_mapitems.doc.cave_coral_usage,
	tiles = {"dfcaverns_cave_coral_end.png", "dfcaverns_cave_coral_end.png", "dfcaverns_cave_coral.png"},
	drop = coral_skeleton,
	light_source = 1,
	paramtype2 = "facedir",
	is_ground_content = false,
	groups = {cracky = 3, dfcaverns_cave_coral = 1, pickaxey = 1, building_block = 1, coral=1, coral_block=1},
	sounds = df_dependencies.sound_stone(),
	on_timer = function(pos)
		if minetest.find_node_near(pos, 1, {water_source}) == nil then
			minetest.set_node(pos, {name=coral_skeleton})
		end
	end,
	_mcl_hardness = 1.5,
	_mcl_blast_resistance = 6,
})

local coral_names = {"df_mapitems:cave_coral_1", "df_mapitems:cave_coral_2", "df_mapitems:cave_coral_3"}
local water_node = df_dependencies.node_name_water_source
minetest.register_abm{
	label = "df_mapitems:shifting_coral",
	nodenames = {"group:dfcaverns_cave_coral"},
	neighbors = {water_node},
	interval = 2,
	chance = 10,
	action = function(pos)
		local node = minetest.get_node(pos)
		minetest.swap_node(pos, {name=coral_names[math.random(1,3)], param2=node.param2})
	end,
}


code:
local S = minetest.get_translator(minetest.get_current_modname())

minetest.register_node("df_mapitems:cave_pearls", {
	description = S("Cave Pearls"),
	tiles = {"dfcaverns_cave_pearl.png"},
	_doc_items_longdesc = df_mapitems.doc.cave_pearls_desc,
	_doc_items_usagehelp = df_mapitems.doc.cave_pearls_usage,
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	groups = {cracky = 2, pickaxey = 2,},
	walkable = false,
	is_ground_content = false,
	climbable = true,
	light_source = 4,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.375, -0.5, -0.375, -0.125, -0.3125, -0.125}, -- NodeBox1
			{0.125, -0.5, -0.1875, 0.3125, -0.375, 0}, -- NodeBox2
			{-0.125, -0.5, 0.25, 0.0625, -0.375, 0.4375}, -- NodeBox3
		}
	},
	on_place = df_mapitems.place_against_surface,
	_mcl_hardness = 1.5,
	_mcl_blast_resistance = 6,
})


code:
local CONFIG_FILE_PREFIX = "dfcaverns_"

df_mapitems.config = {}

local print_settingtypes = false

local function setting(stype, name, default, description)
	local value
	if stype == "bool" then
		value = minetest.settings:get_bool(CONFIG_FILE_PREFIX..name, default)
	elseif stype == "string" then
		value = minetest.settings:get(CONFIG_FILE_PREFIX..name)
	elseif stype == "int" or stype == "float" then
		value = tonumber(minetest.settings:get(CONFIG_FILE_PREFIX..name))
	end
	if value == nil then
		value = default
	end
	df_mapitems.config[name] = value

	if print_settingtypes then
		minetest.debug(CONFIG_FILE_PREFIX..name.." ("..description..") "..stype.." "..tostring(default))
	end
end

setting("float", "glow_worm_delay_multiplier", 10.0, "glow worm growth delay multiplier")
setting("bool", "snareweed_damage", true, "Snareweed causes damage to players")


code:
local S = minetest.get_translator(minetest.get_current_modname())

--glowing mese crystal blocks
minetest.register_node("df_mapitems:glow_mese", {
	description = S("Flawless Mese Block"),
	_doc_items_longdesc = df_mapitems.doc.glow_mese_desc,
	_doc_items_usagehelp = df_mapitems.doc.glow_mese_usage,
	tiles = {"dfcaverns_glow_mese.png"},
	groups = {cracky=3, pickaxey=4, material_stone=1, enderman_takable=1},
	sounds = df_dependencies.sound_glass(),
	is_ground_content = false,
	light_source = 13,
	paramtype = "light",
	use_texture_alpha = "blend",
	drawtype = "glasslike",
	sunlight_propagates = true,
	_mcl_blast_resistance = 1.5,
	_mcl_hardness = 1.5,
})

minetest.register_craft({
	output = 'df_mapitems:mese_crystal 2',
	recipe = {
		{'df_mapitems:glow_mese'},
	}
})

minetest.register_node("df_mapitems:mese_crystal", {
	description = S("Flawless Mese Crystal"),
	_doc_items_longdesc = df_mapitems.doc.glow_mese_desc,
	_doc_items_usagehelp = df_mapitems.doc.glow_mese_usage,
	tiles = {"dfcaverns_glow_mese.png"},
	groups = {cracky = 2, pickaxey=4, material_stone=1, building_block=1, enderman_takable=1},
	paramtype = "light",
	paramtype2 = "facedir",
	drawtype = "mesh",
	mesh = "underch_crystal.obj",
	light_source = 12,
	is_ground_content = false,
	sounds = df_dependencies.sound_glass(),
	use_texture_alpha = "blend",
	sunlight_propagates = true,
	on_place = df_mapitems.place_against_surface,
	_mcl_blast_resistance = 1.5,
	_mcl_hardness = 1.5,
})

minetest.register_craft({
	output = df_dependencies.node_name_mese_crystal .. ' 18',
	recipe = {
		{'df_mapitems:mese_crystal'},
	}
})

if minetest.get_modpath("radiant_damage") and radiant_damage.override_radiant_damage and radiant_damage.config.enable_mese_damage then
	radiant_damage.override_radiant_damage("mese", {
		emitted_by = {
			["df_mapitems:glow_mese"] = radiant_damage.config.mese_damage*12,
			["df_mapitems:mese_crystal"] = radiant_damage.config.mese_damage*9
		}
	})
end


code:
local S = minetest.get_translator(minetest.get_current_modname())

minetest.register_node("df_mapitems:glow_ruby_ore", {
	description = S("Red Crystal Vein"),
	_doc_items_longdesc = df_mapitems.doc.glow_ruby_ore_desc,
	_doc_items_usagehelp = df_mapitems.doc.glow_ruby_ore_usage,
	tiles = {"dfcaverns_glow_ruby_ore.png"},
	is_ground_content = false,
	groups = {cracky=2, pickaxey=3, material_stone=1},
	sounds = df_dependencies.sound_glass(),
	_mcl_blast_resistance = 1.5,
	_mcl_hardness = 1.5,
})

minetest.register_node("df_mapitems:big_crystal", {
	description = S("Giant Red Crystal"),
	_doc_items_longdesc = df_mapitems.doc.big_crystal_desc,
	_doc_items_usagehelp = df_mapitems.doc.big_crystal_usage,
	drawtype = "mesh",
	mesh = "hex_crystal_big.obj",
	tiles = {
		"dfcaverns_glow_ruby4x.png",
		"dfcaverns_glow_ruby.png",
	},
	use_texture_alpha = "blend",
	paramtype = "light",
	paramtype2 = "facedir",
	is_ground_content = false,
	sunlight_propagates = true,
	light_source = 12,
	groups = {cracky=2, dfcaverns_big_crystal = 1, pickaxey=5, material_stone=1, enderman_takable=1},
	sounds = df_dependencies.sound_glass(),
	selection_box = {
		type = "fixed",
		fixed = {-0.5, -0.5, -0.5, 0.5, 3, 0.5},
	},
	collision_box = {
		type = "fixed",
		fixed = {-0.5, -0.5, -0.5, 0.5, 3, 0.5},
	},
	_mcl_blast_resistance = 2,
	_mcl_hardness = 2,
})

minetest.register_node("df_mapitems:med_crystal", {
	description = S("Big Red Crystal"),
	_doc_items_longdesc = df_mapitems.doc.big_crystal_desc,
	_doc_items_usagehelp = df_mapitems.doc.big_crystal_usage,
	drawtype = "mesh",
	mesh = "hex_crystal_med.obj",
	tiles = {
		"dfcaverns_glow_ruby.png",
		"dfcaverns_glow_ruby_quarter.png",
	},
	use_texture_alpha = "blend",
	paramtype = "light",
	paramtype2 = "facedir",
	is_ground_content = false,
	sunlight_propagates = true,
	light_source = 12,
	groups = {cracky=2, dfcaverns_big_crystal = 1, pickaxey=5, material_stone=1},
	sounds = df_dependencies.sound_glass(),
	selection_box = {
		type = "fixed",
		fixed = {-0.25, -0.5, -0.25, 0.25, 1.25, 0.25},
	},
	collision_box = {
		type = "fixed",
		fixed = {-0.25, -0.5, -0.25, 0.25, 1.25, 0.25},
	},
	_mcl_blast_resistance = 2,
	_mcl_hardness = 2,
})

minetest.register_node("df_mapitems:big_crystal_30", {
	description = S("Giant Red Crystal"),
	_doc_items_longdesc = df_mapitems.doc.big_crystal_desc,
	_doc_items_usagehelp = df_mapitems.doc.big_crystal_usage,
	drawtype = "mesh",
	mesh = "hex_crystal_30_big.obj",
	tiles = {
		"dfcaverns_glow_ruby4x.png",
		"dfcaverns_glow_ruby.png",
	},
	use_texture_alpha = "blend",
	paramtype = "light",
	paramtype2 = "facedir",
	sunlight_propagates = true,
	is_ground_content = false,
	light_source = 12,
	drop = "df_mapitems:big_crystal",
	groups = {cracky=2, dfcaverns_big_crystal = 1, pickaxey=5, material_stone=1, enderman_takable=1},
	sounds = df_dependencies.sound_glass(),
	selection_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.625, 0.5, 0.5, 0.375},
			{-0.5, 0.5, -1.25, 0.5, 1.5, -0.25},
			{-0.5, 1.5, -1.875, 0.5, 2.5, -0.875},
			--The following is a more accurate set of collision boxes that theoretically
			--allows the crystal to be climbed like stairs, but in practice the physics
			--don't seem to work quite right so I'm leaving it "simple" for now.
--			{-0.5, -0.5, -0.625, 0.5, 0.0, 0.375},
--			{-0.5, 0.0, -0.9375, 0.5, 0.5, 0.0625},
--			{-0.5, 0.5, -1.25, 0.5, 1.0, -0.25},
--			{-0.5, 1.0, -1.5625, 0.5, 1.5, -0.5625},
--			{-0.5, 1.5, -1.875, 0.5, 2.0, -0.875},
--			{-0.25, 2.0, -1.625, 0.25, 2.5, -1.125},
		},
	},
	collision_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.625, 0.5, 0.5, 0.375},
			{-0.5, 0.5, -1.25, 0.5, 1.5, -0.25},
			{-0.5, 1.5, -1.875, 0.5, 2.5, -0.875},
--			{-0.5, -0.5, -0.625, 0.5, 0.0, 0.375},
--			{-0.5, 0.0, -0.9375, 0.5, 0.5, 0.0625},
--			{-0.5, 0.5, -1.25, 0.5, 1.0, -0.25},
--			{-0.5, 1.0, -1.5625, 0.5, 1.5, -0.5625},
--			{-0.5, 1.5, -1.875, 0.5, 2.0, -0.875},
--			{-0.25, 2.0, -1.625, 0.25, 2.5, -1.125},
		},
	},
	_mcl_blast_resistance = 2,
	_mcl_hardness = 2,
})

minetest.register_node("df_mapitems:med_crystal_30", {
	description = S("Big Red Crystal"),
	_doc_items_longdesc = df_mapitems.doc.big_crystal_desc,
	_doc_items_usagehelp = df_mapitems.doc.big_crystal_usage,
	drawtype = "mesh",
	mesh = "hex_crystal_30_med.obj",
	tiles = {
		"dfcaverns_glow_ruby.png",
		"dfcaverns_glow_ruby_quarter.png",
	},
	use_texture_alpha = "blend",
	paramtype = "light",
	paramtype2 = "facedir",
	sunlight_propagates = true,
	is_ground_content = false,
	light_source = 12,
	drop = "df_mapitems:med_crystal",
	groups = {cracky=2, dfcaverns_big_crystal = 1, pickaxey=5, material_stone=1},
	sounds = df_dependencies.sound_glass(),
	selection_box = {
		type = "fixed",
		fixed = {
			{-0.25, -0.5, -0.3125, 0.25, 0.0, 0.1875},
			{-0.25, 0.0, -0.625, 0.25, 0.5, -0.125},
			{-0.25, 0.5, -0.9375, 0.25, 1.0, -0.4375},
		}
	},
	collision_box = {
		type = "fixed",
		fixed = {
			{-0.25, -0.5, -0.3125, 0.25, 0.0, 0.1875},
			{-0.25, 0.0, -0.625, 0.25, 0.5, -0.125},
			{-0.25, 0.5, -0.9375, 0.25, 1.0, -0.4375},
		},
	},
	_mcl_blast_resistance = 2,
	_mcl_hardness = 2,
})

minetest.register_node("df_mapitems:big_crystal_30_45", {
	description = S("Giant Red Crystal"),
	_doc_items_longdesc = df_mapitems.doc.big_crystal_desc,
	_doc_items_usagehelp = df_mapitems.doc.big_crystal_usage,
	drawtype = "mesh",
	mesh = "hex_crystal_30_45_big.obj",
	tiles = {
		"dfcaverns_glow_ruby4x.png",
		"dfcaverns_glow_ruby.png",
	},
	use_texture_alpha = "blend",
	paramtype = "light",
	paramtype2 = "facedir",
	sunlight_propagates = true,
	is_ground_content = false,
	light_source = 12,
	drop = "df_mapitems:big_crystal",
	groups = {cracky=2, dfcaverns_big_crystal = 1, pickaxey=5, material_stone=1, enderman_takable=1},
	sounds = df_dependencies.sound_glass(),
	selection_box = {
		type = "fixed",
		fixed = {
			{-0.375, -0.5, -0.625, 0.625, 0.5, 0.375},
			{0.0625, 0.5, -1.0625, 1.0625, 1.5, -0.0625},
			{0.5, 1.5, -1.5, 1.5, 2.5, -0.5},
		},
	},
	collision_box = {
		type = "fixed",
		fixed = {
			{-0.375, -0.5, -0.625, 0.625, 0.5, 0.375},
			{0.0625, 0.5, -1.0625, 1.0625, 1.5, -0.0625},
			{0.5, 1.5, -1.5, 1.5, 2.5, -0.5},
		},
	},
	_mcl_blast_resistance = 2,
	_mcl_hardness = 2,
})

minetest.register_node("df_mapitems:med_crystal_30_45", {
	description = S("Big Red Crystal"),
	_doc_items_longdesc = df_mapitems.doc.big_crystal_desc,
	_doc_items_usagehelp = df_mapitems.doc.big_crystal_usage,
	drawtype = "mesh",
	mesh = "hex_crystal_30_45_med.obj",
	tiles = {
		"dfcaverns_glow_ruby4x.png",
		"dfcaverns_glow_ruby.png",
	},
	use_texture_alpha = "blend",
	paramtype = "light",
	paramtype2 = "facedir",
	sunlight_propagates = true,
	is_ground_content = false,
	light_source = 12,
	drop = "df_mapitems:med_crystal",
	groups = {cracky=2, dfcaverns_big_crystal = 1, pickaxey=5, material_stone=1},
	sounds = df_dependencies.sound_glass(),
	selection_box = {
		type = "fixed",
		fixed = {
			{-0.1875, -0.5, -0.3125, 0.3125, 0.0, 0.1875},
			{0.03125, 0.0, -0.53125, 0.53125, 0.5, -0.03125},
			{0.25, 0.5, -0.75, 0.75, 1.0, -0.25},
		},
	},
	collision_box = {
		type = "fixed",
		fixed = {
			{-0.1875, -0.5, -0.3125, 0.3125, 0.0, 0.1875},
			{0.03125, 0.0, -0.53125, 0.53125, 0.5, -0.03125},
			{0.25, 0.5, -0.75, 0.75, 1.0, -0.25},
		},
	},
	_mcl_blast_resistance = 2,
	_mcl_hardness = 2,
})

minetest.register_craft({
	type = "shapeless",
	output = 'df_mapitems:big_crystal_30',
	recipe = {'df_mapitems:big_crystal'},
})
minetest.register_craft({
	type = "shapeless",
	output = 'df_mapitems:big_crystal_30_45',
	recipe = {'df_mapitems:big_crystal_30'},
})
minetest.register_craft({
	type = "shapeless",
	output = 'df_mapitems:big_crystal',
	recipe = {'df_mapitems:big_crystal_30_45'},
})
minetest.register_craft({
	type = "shapeless",
	output = 'df_mapitems:med_crystal_30',
	recipe = {'df_mapitems:med_crystal'},
})
minetest.register_craft({
	type = "shapeless",
	output = 'df_mapitems:med_crystal_30_45',
	recipe = {'df_mapitems:med_crystal_30'},
})
minetest.register_craft({
	type = "shapeless",
	output = 'df_mapitems:med_crystal',
	recipe = {'df_mapitems:med_crystal_30_45'},
})

local c_stone = minetest.get_content_id(df_dependencies.node_name_stone)
local c_air = minetest.get_content_id("air")
local c_big_crystal = minetest.get_content_id("df_mapitems:big_crystal")
local c_med_crystal = minetest.get_content_id("df_mapitems:med_crystal")
local c_big_crystal_30 = minetest.get_content_id("df_mapitems:big_crystal_30")
local c_med_crystal_30 = minetest.get_content_id("df_mapitems:med_crystal_30")
local c_big_crystal_30_45 = minetest.get_content_id("df_mapitems:big_crystal_30_45")
local c_med_crystal_30_45 = minetest.get_content_id("df_mapitems:med_crystal_30_45")
local c_glow_ore = minetest.get_content_id("df_mapitems:glow_ruby_ore")

df_mapitems.place_big_crystal = function(data, data_param2, vi, ceiling)
	local orientation = math.random()
	if orientation < 0.33 then
		if math.random() > 0.5 then
			data[vi] = c_big_crystal
		else
			data[vi] = c_med_crystal
		end
	elseif orientation < 0.66 then
		if math.random() > 0.5 then
			data[vi] = c_big_crystal_30
		else
			data[vi] = c_med_crystal_30
		end
	else
		if math.random() > 0.5 then
			data[vi] = c_big_crystal_30_45
		else
			data[vi] = c_med_crystal_30_45
		end
	end
	if ceiling then
		data_param2[vi] = math.random(20,23)
	else
		data_param2[vi] = math.random(0,3)
	end

end

df_mapitems.place_big_crystal_cluster = function(area, data, data_param2, vi, radius, ceiling)
	local y
	if ceiling then y = -1 else y = 1 end
	local pos = area:position(vi)
	for li in area:iterp(vector.add(pos, -radius), vector.add(pos, radius)) do
		local adjacent = li + y*area.ystride
		if math.random() > 0.5  and data[li] == c_stone and data[adjacent] == c_air then
			df_mapitems.place_big_crystal(data, data_param2, adjacent, ceiling)
			data[li] = c_glow_ore
		end
	end
end


code:
local S = minetest.get_translator(minetest.get_current_modname())

minetest.register_node("df_mapitems:salt_crystal", {
	description = S("Luminous Salt Crystal"),
	_doc_items_longdesc = df_mapitems.doc.salt_desc,
	_doc_items_usagehelp = df_mapitems.doc.salt_usage,
	tiles = {"dfcaverns_salt_crystal.png"},
	groups = {cracky = 2, pickaxey = 1, shovely=1, material_stone=1},
	paramtype = "light",
	paramtype2 = "facedir",
	drawtype = "mesh",
	mesh = "underch_crystal.obj",
	light_source = 6,
	sounds = df_dependencies.sound_glass(),
	use_texture_alpha = "blend",
	sunlight_propagates = true,
	is_ground_content = false,
	on_place = df_mapitems.place_against_surface,
	_mcl_blast_resistance = 1,
	_mcl_hardness = 1,
})

minetest.register_node("df_mapitems:salty_cobble", {
	description = S("Salty Cobble"),
	_doc_items_longdesc = df_mapitems.doc.salty_cobble_desc,
	_doc_items_usagehelp = df_mapitems.doc.salty_cobble_desc,
	tiles = {df_dependencies.texture_cobble .. "^dfcaverns_salty.png"},
	groups = {cracky = 3, stone = 1, lava_heatable = 1, pickaxey = 1, material_stone=1},
	_magma_conduits_heats_to = df_dependencies.node_name_cobble,
	is_ground_content = false,
	light_source = 2,
	drop = df_dependencies.node_name_cobble,
	sounds = df_dependencies.sound_stone(),
	_mcl_blast_resistance = 6,
	_mcl_hardness = 2,
})


code:
df_mapitems.doc = {}

if not minetest.get_modpath("doc") then
	return
end

local S = minetest.get_translator(minetest.get_current_modname())

df_mapitems.doc.cave_moss_desc = S("Cave moss is technically a form of mold, but fortunately a relatively benign one given its ubiquity. Its fibers form a tough but springy mat over the surface of any organic-rich soil that accumulates deep underground.")
df_mapitems.doc.cave_moss_usage = S("Cave moss has no known uses aside from the faint glow it emits. It dies when exposed to bright light sources such as the Sun.")
df_mapitems.doc.floor_fungus_desc = S("Floor fungus produces a thin, slick film that spreads through the cracks of broken rock. Its ability to subsist on the tiniest traces of nutrients means it's found in relatively harsh underground environments.")
df_mapitems.doc.floor_fungus_usage = S("Floor fungus has no known uses. It can penetrate deeply into cobblestone constructions if an infestation gets hold, but it is difficult to transport and is inhibited by light so it hasn't spread beyond the deep caverns.")

df_mapitems.doc.sand_scum_desc = S("Sand scum is a crust of algae that sometimes accumulates on wet sand deep underground, somehow managing to eke out a meager living from the phosphorescent light emitted by other organisms.")
df_mapitems.doc.sand_scum_usage = S("Sand scum is useless. You can get sand out of it, at least.")

df_mapitems.doc.pebble_fungus_desc = S("Soil that is rich enough to support gigantic mushrooms can support innumerable smaller ones as well. Pebble fungus is a prolific form of mushroom that covers the soil in small spheroidal fruiting bodies.")
df_mapitems.doc.pebble_fungus_usage = S("Pebble fungus grows in soil that is rich enough for farming.")

df_mapitems.doc.stillworm_desc = S("Stillworm is not actually a kind of worm, but a sort of fungus that looks uncannily like pale, motionless earthworms intertwined with the soil.")
df_mapitems.doc.stillworm_usage = S("Stillworm grows in soil that is rich enough for farming.")

df_mapitems.doc.rock_rot_desc = S("A highly aggressive form of lichen that eats into solid rock, turning its upper surfaces rough and a little spongy.")
df_mapitems.doc.rock_rot_usage = S("Organic material accumulates in the enlarged pores of rock rot, but not enough to be considered \"soil\" in the usable sense.")

df_mapitems.doc.spongestone_desc = S("Spongestone is the result of advanced rock rot in its ultimate form. The stone has become so riddled with pores and cavities that it's no longer really stone.")
df_mapitems.doc.spongestone_usage = S("Although a strong mineral matrix remains, spongestone has enough organic content that it can be used as soil for farming.")

df_mapitems.doc.hoar_moss_desc = S("Hoar moss is a strange glowing crust that sometimes forms on the surface of water flowing over ice.")
df_mapitems.doc.hoar_moss_usage = S("Hoar moss has no known use aside from providing a faint source of light.")

df_mapitems.doc.glow_worms_desc = S("Glistening strings of silk hang from the ceilings of some of the larger caverns, lit by the millions of tiny bioluminescent worms that spun them. Glow worms prey on the insects they lure and entangle with their faux starry sky - and sometimes the occasional bat or other larger flying beast.")
df_mapitems.doc.glow_worms_usage = S("Glow worms can be harvested and used as a source of light but they die when exposed to light significantly brighter than themselves or when immersed in water. A colony of glow worms hung in a hospitable environment will undergo a modest amount of growth, allowing it to be divided and propagated.")

df_mapitems.doc.snareweed_desc = S("A nasty kelp-like plant that grows in patches on the floor of the Sunless Sea. Its reflective patches draw in the unwary and then its prickly barbs catch and hold small creatures.")
df_mapitems.doc.snareweed_usage = S("Snareweed has no practical use, its fibers disintegrate when they dry.")

df_mapitems.doc.cave_coral_desc = S("A rare form of coral found only deep underground in the Sunless Sea, cave coral grows hanging from the ceilings of flooded caverns.")
df_mapitems.doc.cave_coral_usage = S("Aside from their aesthetic beauty, cave corals can be harvested for simple building materials.")

df_mapitems.doc.flowstone_desc = S("Flowstone is a carbonate-rich rock formation deposited by flowing water. It consists of minerals that the water dissolved earlier as it widens cracks and fissures into caves.")
df_mapitems.doc.flowstone_usage = S("Aside from the aesthetic beauty of its formations flowstone has no special properties or uses.")
df_mapitems.doc.dripstone_desc = S("The iconic stalactites and stalagmites found in caverns are composed of flowstone (or 'dripstone' in the case of these formations). Moist dripstone is still undergoing growth, whereas dry dripstone is found in 'dead' caverns once the source of water that created them ceases.")
df_mapitems.doc.dripstone_usage = S("Although stalagmites are blunter than the stalactites above them, they can cause extra damage to the unwary caver who falls on them.")
df_mapitems.doc.icicle_desc = S("Ice formed by water dripping slowly into a cold environment, icicles tend to be exceptionally pure and clear.")
df_mapitems.doc.icicle_usage = S("Falling onto an icicle is particularly damaging.")

df_mapitems.doc.glow_mese_desc = S("Deep in the infernal conditions of the magma sea, over the course of millions of years, mese crystals grow into flawless blocks that glow bright with strange energies.")
df_mapitems.doc.glow_mese_usage = S("These blocks can be broken down into a large number of mese crystals, but cannot be artificially reassembled.")

df_mapitems.doc.glow_ruby_ore_desc = S("Large, dry caverns deep underground are well suited to aeons-long processes that concentrate crystalline substances in their walls. This rock is riddled with veins of the stuff.")
df_mapitems.doc.glow_ruby_ore_usage = S("Aside from its aesthetic value this rock has no particular use.")

df_mapitems.doc.big_crystal_desc = S("Monolithic crystals of this size form only over extremely long periods deep underground, in large long-lived cavities that allow them room to grow. Water and the life it hosts tend to disrupt the formation process of these crystals so they're only found in dry environments.")
df_mapitems.doc.big_crystal_usage = S("Aside from its aesthetic value this crystal has no particular use.")

df_mapitems.doc.cave_pearls_desc = S("These nodules are actually calcified bacterial colonies.")
df_mapitems.doc.cave_pearls_usage = S("Aside from their soft glow and beauty, cave pearls have no practical use. Except perhaps as handholds for climbing.")

df_mapitems.doc.castle_coral_desc = S("Deep under the surface of the Sunless Sea are the rare and beautiful Castle Corals, so named due to their resemblance to small undersea castles.")
df_mapitems.doc.castle_coral_usage = S("Castle Coral has little practical use aside from perhaps as a distinctive-looking building material.")

df_mapitems.doc.salt_desc = S("A crystal of salt grown from water that percolated through the depths of the earth, picking up all manner of minerals as it went.")
df_mapitems.doc.salt_usage = S("Traces of Mese must have been dissolved by the water as this crystal has an inherent glow to it. Not enough Mese to be useful as a reagent, unfortunately.")

df_mapitems.doc.salty_cobble_desc = S("Much water has seeped through the cracks in this rock and then quickly evaporated, leaving a crust of salt laced throughout.")
df_mapitems.doc.salty_cobble_usage = S("Attemping to mine this rock knocks the salt crust away, leaving only base stone.")


code:
local S = minetest.get_translator(minetest.get_current_modname())

-----------------------------------------------

df_mapitems.dry_stalagmite_ids = subterrane.register_stalagmite_nodes("df_mapitems:dry_stal", {
	description = S("Dry Dripstone"),
	_doc_items_longdesc = df_mapitems.doc.dripstone_desc,
	_doc_items_usagehelp = df_mapitems.doc.dripstone_usage,
	tiles = {
		df_dependencies.texture_stone .. "^[brighten",
	},
	groups = {cracky = 3, stone = 2, pickaxey=1, building_block=1, material_stone=1},
	sounds = df_dependencies.sound_stone(),
	is_ground_content = false,
	_mcl_blast_resistance = 6,
	_mcl_hardness = 1.5,
})

minetest.register_node("df_mapitems:dry_flowstone", {
	description = S("Dry Flowstone"),
	_doc_items_longdesc = df_mapitems.doc.flowstone_desc,
	_doc_items_usagehelp = df_mapitems.doc.flowstone_usage,
	tiles = {df_dependencies.texture_stone .. "^[brighten"},
	groups = {cracky = 3, stone = 1, lava_heatable = 1, pickaxey=1, building_block=1, material_stone=1},
	_magma_conduits_heats_to = df_dependencies.node_name_cobble,
	is_ground_content = false,
	drop = df_dependencies.node_name_cobble,
	sounds = df_dependencies.sound_stone(),
	_mcl_blast_resistance = 6,
	_mcl_hardness = 1.5,
})

-----------------------------------------------

df_mapitems.wet_stalagmite_ids = subterrane.register_stalagmite_nodes("df_mapitems:wet_stal", {
	description = S("Wet Dripstone"),
	_doc_items_longdesc = df_mapitems.doc.dripstone_desc,
	_doc_items_usagehelp = df_mapitems.doc.dripstone_usage,
	tiles = {
		df_dependencies.texture_stone .. "^[brighten^dfcaverns_dripstone_streaks.png",
	},
	groups = {cracky = 3, stone = 2, subterrane_wet_dripstone = 1, pickaxey=1, building_block=1, material_stone=1},
	sounds = df_dependencies.sound_stone(),
	is_ground_content = false,
	_mcl_blast_resistance = 6,
	_mcl_hardness = 1.5,
}, "df_mapitems:dry_stal")

minetest.register_node("df_mapitems:wet_flowstone", {
	description = S("Wet Flowstone"),
	_doc_items_longdesc = df_mapitems.doc.flowstone_desc,
	_doc_items_usagehelp = df_mapitems.doc.flowstone_usage,
	tiles = {df_dependencies.texture_stone .. "^[brighten^dfcaverns_dripstone_streaks.png"},
	groups = {cracky = 3, stone = 1, subterrane_wet_dripstone = 1, lava_heatable = 1, pickaxey=1, building_block=1, material_stone=1},
	_magma_conduits_heats_to = "df_mapitems:dry_flowstone",
	is_ground_content = false,
	drop = df_dependencies.node_name_cobble,
	sounds = df_dependencies.sound_stone(),
	_mcl_blast_resistance = 6,
	_mcl_hardness = 1.5,
})

-----------------------------------------------

df_mapitems.icicle_ids = subterrane.register_stalagmite_nodes("df_mapitems:icicle", {
	description = S("Icicle"),
	_doc_items_longdesc = df_mapitems.doc.icicle_desc,
	_doc_items_usagehelp = df_mapitems.doc.icicle_usage,
	tiles = {
		df_dependencies.texture_ice,
	},
	groups = {cracky = 3, puts_out_fire = 1, cools_lava = 1, slippery = 3, pickaxey=1, building_block=1, handy=1, slippery=3, building_block=1, ice=1},
	sounds = df_dependencies.sound_glass(),
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.5,
})


code:
local S = minetest.get_translator(minetest.get_current_modname())

local growth_multiplier = 1
if minetest.get_modpath("df_farming") then
	growth_multiplier = df_farming.config.plant_growth_time
end

minetest.register_node("df_mapitems:glow_worm", {
	description = S("Glow Worms"),
	_doc_items_longdesc = df_mapitems.doc.glow_worms_desc,
	_doc_items_usagehelp = df_mapitems.doc.glow_worms_usage,
	tiles = {
		{
			name = "dfcaverns_glow_worm_animated.png",
			animation = {
				type = "vertical_frames",
				aspect_w = 16,
				aspect_h = 16,
				length = 4.0,
			},
		},
	},
	inventory_image = "dfcaverns_glow_worm.png",
	wield_image = "dfcaverns_glow_worm.png",
	is_ground_content = false,
	groups = {oddly_breakable_by_hand=3, light_sensitive_fungus = 12, shearsy=1, swordy=1, destroy_by_lava_flow=1},
	_dfcaverns_dead_node = "air",
	light_source = 9,
	paramtype = "light",
	drawtype = "plantlike",
	walkable = false,
	buildable_to = true,
	floodable = true,
	visual_scale = 1.0,
	_mcl_blast_resistance = 0.2,
	_mcl_hardness = 0.2,
	after_place_node = function(pos, placer)
		if df_mapitems.config.glow_worm_delay_multiplier > 0 then
			minetest.get_node_timer(pos):start(math.random(
				df_mapitems.config.glow_worm_delay_multiplier * growth_multiplier * 0.75,
				df_mapitems.config.glow_worm_delay_multiplier * growth_multiplier * 1.25))
		end
	end,
	on_timer = function(pos, elapsed)
		local below = {x=pos.x, y=pos.y-1, z=pos.z}
		if minetest.get_node(below).name == "air" then
			minetest.set_node(below, {name="df_mapitems:glow_worm"})
			if math.random() > 0.5 then
				minetest.get_node_timer(below):start(math.random(
				df_mapitems.config.glow_worm_delay_multiplier * growth_multiplier * 0.75,
				df_mapitems.config.glow_worm_delay_multiplier * growth_multiplier * 1.25))
			end
		end
	end,
})

local c_air = minetest.get_content_id("air")
local c_worm = minetest.get_content_id("df_mapitems:glow_worm")

df_mapitems.glow_worm_ceiling = function(area, data, vi)
	local ystride = area.ystride
	local bi = vi - ystride
	if data[vi] == c_air and data[bi] == c_air then
		data[vi] = c_worm
		data[bi] = c_worm
		if math.random(2) == 1 then
			bi = bi - ystride
			if data[bi] == c_air then
				data[bi] = c_worm
				if math.random(2) == 1 then
					bi = bi - ystride
					if data[bi] == c_air then
						data[bi] = c_worm
					end
				end
			end
		end
	end
end


code:
local S = minetest.get_translator(minetest.get_current_modname())

local function soil_type_spread(label, node_to_spread, target_node)
	minetest.register_abm{
		label = label,
		nodenames = {target_node},
		neighbors = {node_to_spread},
		interval = 60,
		chance = 15,
		catch_up = true,
		action = function(pos)
			local above_def = minetest.registered_nodes[minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name]
			if above_def and (above_def.buildable_to == true or above_def.walkable == false) then
				minetest.swap_node(pos, {name=node_to_spread})
			end
		end,
	}
end

local farming_soil = df_dependencies.node_name_dirt_furrowed
local farming_soil_wet = df_dependencies.node_name_dirt_wet

--------------------------------------------------
-- Cave moss

-- cyan/dark cyan

local dirt_texture = df_dependencies.texture_dirt
local sand_texture = df_dependencies.texture_sand

local dirt_node = df_dependencies.node_name_dirt
local sand_node = df_dependencies.node_name_sand
local stone_node = df_dependencies.node_name_stone
local cobble_node = df_dependencies.node_name_cobble

minetest.register_node("df_mapitems:dirt_with_cave_moss", {
	description = S("Dirt with Cave Moss"),
	_doc_items_longdesc = df_mapitems.doc.cave_moss_desc,
	_doc_items_usagehelp = df_mapitems.doc.cave_moss_usage,
	tiles = {dirt_texture .. "^dfcaverns_cave_moss.png", dirt_texture,
		{name = dirt_texture .. "^(dfcaverns_cave_moss.png^[mask:dfcaverns_ground_cover_side_mask.png)",
			tileable_vertical = false}},
	drop = dirt_node,
	is_ground_content = false,
	light_source = 2,
	paramtype = "light",
	groups = {crumbly = 3, soil = 1, light_sensitive_fungus = 8, handy=1,shovely=1,dirt=2, soil_sapling=2, soil_sugarcane=1, cultivatable=1, enderman_takable=1, building_block=1, compostability=30, opaque=1},
	sounds = df_dependencies.sound_dirt({footstep = {name = df_dependencies.soundfile_grass_footstep, gain = 0.25},}),
	soil = {
		base = "df_mapitems:dirt_with_cave_moss",
		dry = farming_soil,
		wet = farming_soil_wet
	},
	_dfcaverns_dead_node = dirt_node,
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.6,
})

soil_type_spread("df_mapitems:cave_moss_spread", "df_mapitems:dirt_with_cave_moss", dirt_node)

---------------------------------------------------------------
-- Sand scum

minetest.register_node("df_mapitems:sand_scum", {
	description = S("Sand Scum"),
	_doc_items_longdesc = df_mapitems.doc.sand_scum_desc,
	_doc_items_usagehelp = df_mapitems.doc.sand_scum_usage,
	tiles = {"dfcaverns_ground_cover_sand_scum.png", sand_texture,
		{name = sand_texture .. "^(dfcaverns_ground_cover_sand_scum.png^[mask:dfcaverns_ground_cover_side_mask.png)",
			tileable_vertical = false}},
	drop = sand_node,
	is_ground_content = false,
	light_source = 2,
	paramtype = "light",
	groups = {crumbly = 3, soil = 1, light_sensitive_fungus = 8, handy=1,shovely=1, falling_node=1, sand=1, soil_sugarcane=1, enderman_takable=1, building_block=1, material_sand=1, opaque=1},
	sounds = df_dependencies.sound_sand({footstep = {name = "dfcaverns_squish", gain = 0.25},}),
	_dfcaverns_dead_node = sand_node,
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.5,
})

soil_type_spread("df_mapitems:sand_scum_spread", "df_mapitems:sand_scum", sand_node)

---------------------------------------------------------------
-- Pebble fungus

minetest.register_node("df_mapitems:dirt_with_pebble_fungus", {
	description = S("Dirt with Pebble Fungus"),
	_doc_items_longdesc = df_mapitems.doc.pebble_fungus_desc,
	_doc_items_usagehelp = df_mapitems.doc.pebble_fungus_usage,
	tiles = {"dfcaverns_ground_cover_pebble_fungus.png", dirt_texture,
		{name = dirt_texture .. "^(dfcaverns_ground_cover_pebble_fungus.png^[mask:dfcaverns_ground_cover_side_mask.png)",
			tileable_vertical = false}},
	drop = dirt_node,
	is_ground_content = false,
	light_source = 2,
	paramtype = "light",
	groups = {crumbly = 3, soil = 1, light_sensitive_fungus = 8, handy=1,shovely=1,dirt=2, soil_sapling=2, soil_sugarcane=1, cultivatable=1, enderman_takable=1, building_block=1, compostability=30, opaque=1},
	sounds = df_dependencies.sound_dirt(),
	soil = {
		base = "df_mapitems:dirt_with_pebble_fungus",
		dry = farming_soil,
		wet = farming_soil_wet
	},
	_dfcaverns_dead_node = dirt_node,
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.6,
})

soil_type_spread("df_mapitems:pebble_fungus_spread", "df_mapitems:dirt_with_pebble_fungus", dirt_node)

---------------------------------------------------------------
-- Stillworm

minetest.register_node("df_mapitems:dirt_with_stillworm", {
	description = S("Dirt with Stillworm"),
	_doc_items_longdesc = df_mapitems.doc.stillworm_desc,
	_doc_items_usagehelp = df_mapitems.doc.stillworm_usage,
	tiles = {dirt_texture .. "^dfcaverns_ground_cover_stillworm.png", dirt_texture,
		{name = dirt_texture .. "^(dfcaverns_ground_cover_stillworm.png^[mask:dfcaverns_ground_cover_side_mask.png)",
			tileable_vertical = false}},
	drop = dirt_node,
	is_ground_content = false,
	light_source = 2,
	paramtype = "light",
	groups = {crumbly = 3, soil = 1, light_sensitive_fungus = 8, handy=1,shovely=1,dirt=2, soil_sapling=2, soil_sugarcane=1, cultivatable=1, enderman_takable=1, building_block=1, compostability=30, opaque=1},
	sounds = df_dependencies.sound_dirt({footstep = {name = df_dependencies.soundfile_grass_footstep, gain = 0.25},}),
	soil = {
		base = "df_mapitems:dirt_with_stillworm",
		dry = farming_soil,
		wet = farming_soil_wet
	},
	_dfcaverns_dead_node = dirt_node,
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.6,
})

soil_type_spread("df_mapitems:stillworm_spread", "df_mapitems:dirt_with_stillworm", dirt_node)

---------------------------------------------------------------
-- Spongestone / Rock rot

minetest.register_node("df_mapitems:spongestone", {
	description = S("Spongestone"),
	_doc_items_longdesc = df_mapitems.doc.sponge_stone_desc,
	_doc_items_usagehelp = df_mapitems.doc.sponge_stone_usage,
	tiles = {"dfcaverns_ground_cover_sponge_stone.png"},
	drop = dirt_node,
	is_ground_content = false,
	paramtype = "light",
	groups = {crumbly = 3, soil = 1, light_sensitive_fungus = 8, shovely=1,dirt=2, enderman_takable=1, building_block=1, compostability=10, opaque=1},
	sounds = df_dependencies.sound_dirt(),
	soil = {
		base = "df_mapitems:spongestone",
		dry = farming_soil,
		wet = farming_soil_wet
	},
	_dfcaverns_dead_node = dirt_node,
	_mcl_blast_resistance = 0.6,
	_mcl_hardness = 0.6,
})

minetest.register_node("df_mapitems:rock_rot", {
	description = S("Rock Rot"),
	_doc_items_longdesc = df_mapitems.doc.rock_rot_desc,
	_doc_items_usagehelp = df_mapitems.doc.rock_rot_usage,
	tiles = {df_dependencies.texture_stone .. "^dfcaverns_ground_cover_rock_rot.png", df_dependencies.texture_stone,
		{name = df_dependencies.texture_stone .. "^(dfcaverns_ground_cover_rock_rot.png^[mask:dfcaverns_ground_cover_side_mask.png)",
			tileable_vertical = false}},
	drop = df_dependencies.node_name_cobble,
	is_ground_content = false,
	light_source = 2,
	paramtype = "light",
	groups = {crumbly = 3, soil = 1, light_sensitive_fungus = 8, shovely=1,dirt=2, enderman_takable=1, building_block=1, compostability=5, opaque=1},
	sounds = df_dependencies.sound_dirt(),
	_dfcaverns_dead_node = stone_node,
	_mcl_blast_resistance = 3,
	_mcl_hardness = 1,
})

soil_type_spread("df_mapitems:rock_rot_spread", "df_mapitems:rock_rot", stone_node)
soil_type_spread("df_mapitems:spongestone_spread", "df_mapitems:spongestone", "df_mapitems:rock_rot")

--------------------------------------------------
-- floor fungus

-- white/yellow

minetest.register_node("df_mapitems:cobble_with_floor_fungus", {
	description = S("Cobblestone with Floor Fungus"),
	_doc_items_longdesc = df_mapitems.doc.floor_fungus_desc,
	_doc_items_usagehelp = df_mapitems.doc.floor_fungus_usage,
	tiles = {df_dependencies.texture_cobble .. "^dfcaverns_floor_fungus.png"},
	drop = cobble_node,
	paramtype = "light",
	is_ground_content = false,
	groups = {cracky = 3, stone = 2, slippery = 1, light_sensitive_fungus = 8, df_caverns_floor_fungus = 1, pickaxey=1, building_block=1, material_stone=1, opaque=1},
	_dfcaverns_dead_node = df_dependencies.node_name_cobble,
	sounds = df_dependencies.sound_stone({footstep = {name = "dfcaverns_squish", gain = 0.25},}),
	_mcl_blast_resistance = 6,
	_mcl_hardness = 1.5,
})

minetest.register_node("df_mapitems:cobble_with_floor_fungus_fine", {
	description = S("Cobblestone with Floor Fungus"),
	_doc_items_longdesc = df_mapitems.doc.floor_fungus_desc,
	_doc_items_usagehelp = df_mapitems.doc.floor_fungus_usage,
	tiles = {df_dependencies.texture_cobble .. "^dfcaverns_floor_fungus_fine.png"},
	drop = cobble_node,
	is_ground_content = false,
	paramtype = "light",
	groups = {cracky = 3, stone = 2, slippery = 1, light_sensitive_fungus = 8, df_caverns_floor_fungus = 1, pickaxey=1, building_block=1, material_stone=1, opaque=1},
	_dfcaverns_dead_node = df_dependencies.node_name_cobble,
	sounds = df_dependencies.sound_stone({footstep = {name = "dfcaverns_squish", gain = 0.25},}),
	_mcl_blast_resistance = 6,
	_mcl_hardness = 1.5,
	on_timer = function(pos, elapsed)
		minetest.swap_node(pos, {name="df_mapitems:cobble_with_floor_fungus"})
	end,
	on_destruct = function(pos)
		minetest.get_node_timer(pos):stop()
	end,
})

minetest.register_abm{
	label = "df_mapitems:floor_fungus_spread",
	nodenames = {cobble_node},
	neighbors = {"group:df_caverns_floor_fungus"},
	interval = 60,
	chance = 10,
	catch_up = true,
	action = function(pos)
		local above_def = minetest.registered_nodes[minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name]
		if above_def and (above_def.buildable_to == true or above_def.walkable == false) then
			minetest.swap_node(pos, {name="df_mapitems:cobble_with_floor_fungus_fine"})
			if math.random() > 0.5 then
				minetest.get_node_timer(pos):start(math.random(1000, 10000))
			end
		end
	end,
}

------------------------------------------------------
-- Hoar moss

minetest.register_node("df_mapitems:ice_with_hoar_moss", {
	description = S("Ice with Hoar Moss"),
	_doc_items_longdesc = df_mapitems.doc.hoar_moss_desc,
	_doc_items_usagehelp = df_mapitems.doc.hoar_moss_usage,
	tiles = {df_dependencies.texture_ice .. "^dfcaverns_hoar_moss.png"},
	drop = df_dependencies.node_name_ice,
	paramtype = "light",
	light_source = 2,
	is_ground_content = false,
	groups = {cracky = 3, puts_out_fire = 1, cools_lava = 1, slippery = 2, light_sensitive_fungus = 8, handy=1,pickaxey=1, building_block=1, ice=1, opaque=1},
	sounds = df_dependencies.sound_glass(),
	_dfcaverns_dead_node = df_dependencies.node_name_ice,
	_mcl_blast_resistance = 0.5,
	_mcl_hardness = 0.5,
})

----------------------------------------------------------------
-- Footprint-capable nodes

if minetest.get_modpath("footprints") then
	local HARDPACK_PROBABILITY = tonumber(minetest.settings:get("footprints_hardpack_probability")) or 0.9 -- Chance walked dirt/grass is worn and compacted to footprints:trail.
	local HARDPACK_COUNT = tonumber(minetest.settings:get("footprints_hardpack_count")) or 10 -- Number of times the above chance needs to be passed for soil to compact.

	footprints.register_trample_node("df_mapitems:dirt_with_cave_moss", {
		trampled_node_def_override = {description = S("Dirt with Cave Moss and Footprint"),},
		hard_pack_node_name = "footprints:trail",
		footprint_opacity = 128,
		hard_pack_probability = HARDPACK_PROBABILITY,
		hard_pack_count = HARDPACK_COUNT,
	})

	footprints.register_trample_node("df_mapitems:sand_scum", {
		trampled_node_def_override = {description = S("Sand Scum with Footprint"),},
		hard_pack_node_name = df_dependencies.node_name_sand,
		footprint_opacity = 128,
		hard_pack_probability = HARDPACK_PROBABILITY,
		hard_pack_count = HARDPACK_COUNT * 0.5,
	})

	footprints.register_trample_node("df_mapitems:spongestone", {
		trampled_node_def_override = {description = S("Spongestone with Footprint"),},
		hard_pack_node_name = "footprints:trail",
		footprint_opacity = 128,
		hard_pack_probability = HARDPACK_PROBABILITY,
		hard_pack_count = HARDPACK_COUNT * 2,
	})

	footprints.register_trample_node("df_mapitems:dirt_with_pebble_fungus", {
		trampled_node_def_override = {description = S("Dirt with Pebble Fungus and Footprint"),},
		hard_pack_node_name = "footprints:trail",
		footprint_opacity = 128,
		hard_pack_probability = HARDPACK_PROBABILITY,
		hard_pack_count = HARDPACK_COUNT,
	})

	footprints.register_trample_node("df_mapitems:dirt_with_stillworm", {
		trampled_node_def_override = {description = S("Dirt with Stillworm and Footprint"),},
		hard_pack_node_name = "footprints:trail",
		footprint_opacity = 192,
		hard_pack_probability = HARDPACK_PROBABILITY,
		hard_pack_count = HARDPACK_COUNT,
	})
end


code:
df_mapitems = {}

local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)

--load companion lua files
dofile(modpath.."/config.lua")
dofile(modpath.."/doc.lua")
dofile(modpath.."/aliases.lua")
dofile(modpath.."/util.lua")

dofile(modpath.."/ground_cover.lua")
dofile(modpath.."/glow_worms.lua")
dofile(modpath.."/flowstone.lua")
dofile(modpath.."/snareweed.lua")
dofile(modpath.."/cave_coral.lua")

dofile(modpath.."/crystals_mese.lua")
dofile(modpath.."/crystals_ruby.lua")
dofile(modpath.."/crystals_salt.lua")

dofile(modpath.."/veinstone.lua")
dofile(modpath.."/cave_pearls.lua")
dofile(modpath.."/castle_coral.lua")