code:
# Ropes

This mod adds "rope boxes", blocks that when placed in world will automatically lower a rope at 1 meter per second until it reaches a fixed maximum length. The basic rope box produces 50m of rope by default and there are up to eight additional rope box types that produce multiples of that rope length - 100m, 150m, and so forth up to 450m. The number of rope boxes and the length of a standard rope length can be configured via the settings menu.

The rope stops lowering if it reaches an obstruction. Ropes can be cut using an axe or other choppy tool at any location and when they're cut the bottom half of the rope will disappear, dropping any climbers. The same happens to the entire rope if the rope box at the top of the rope is removed. Cutting the rope doesn't reduce the maximum length of rope the rope box will produce if it's removed and rebuilt again. Ropes are flammable. They respect protection settings - if the player that placed the rope box isn't permitted to build in an area then the rope descending from that box will treat it as an obstruction.

Also included is a rope ladder that behaves similarly, though it only comes in one standard maximum length - 50m by default, again changeable in settings.

This mod will also enhance default wood ladders and steel ladders to make them "extendable", capable of building upward independent of support to a setting-defined limit (defaulting to 5 nodes for wood and 15 nodes for steel ladders). This can be disabled if undesired.

This mod retains optional backward compatibility with the crafting items from the vines mod (anything with group "vines" can be used to make rope boxes and rope ladders). Ropes can also be made from cotton, available via an optional dependency on the farming mod.

In-game documentation is provided via an optional dependency on the doc mod.


code:
local modpath = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(modpath.."/intllib.lua")

if ropes.bridges_enabled then

local bridge_on_place = function(itemstack, placer, pointed_thing)
    -- Shall place item and return the leftover itemstack.
    -- The placer may be any ObjectRef or nil.
    -- default: minetest.item_place
	if placer == nil then
		return minetest.item_place(itemstack, placer, pointed_thing)
	end

	local above = pointed_thing.above
	local under = pointed_thing.under

	if above.x == under.x and above.z == under.z and above.y > under.y then
		-- we're aimed downward at a buildable node from above.
		-- determine the direction the placer lies relative to this node.
		local new_under = vector.new(under)
		local placer_pos = placer:get_pos()
		local diff_x = placer_pos.x - under.x
		local diff_z = placer_pos.z - under.z
		if math.abs(diff_x) > math.abs(diff_z) then
			-- placer is displaced along the X axis relative to the target
			if diff_x > 0 then
				new_under.x = under.x - 1
			else
				new_under.x = under.x + 1
			end
		else
			-- placer is displaced along the Z axis relative to the target
			if diff_z > 0 then
				new_under.z = under.z - 1
			else
				new_under.z = under.z + 1
			end
		end
		if minetest.registered_nodes[minetest.get_node(new_under).name].buildable_to then
			local new_pointed_thing = {type="node", under=new_under, above={x=new_under.x, y=new_under.y+1, z=new_under.z}}
			return minetest.item_place(itemstack, placer, new_pointed_thing)
		end
	end

	return minetest.item_place(itemstack, placer, pointed_thing)
end

minetest.register_node("ropes:wood_bridge", {
	description = S("Wooden Bridge"),
	_doc_items_longdesc = ropes.doc.wooden_bridge_longdesc,
	_doc_items_usagehelp = ropes.doc.wooden_bridge_usagehelp,
	tiles = {
		"default_wood.png", "default_wood.png",
		"default_wood.png^[transformR270", "default_wood.png^[transformR90",
		"default_wood.png^[transformR270", "default_wood.png^[transformR90",
	},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	groups = {choppy = 2, flammable = 2, oddly_breakable_by_hand = 1, flow_through = 1, fence = 1, wall = 1},
	sounds = default.node_sound_wood_defaults(),
	node_box = {
		type = "fixed",
		fixed = {
			{-0.5, 0.375, -0.5, 0.5, 0.5, 0.5}, -- Platform
			{-0.375, -0.5, -0.5, 0.375, -0.375, -0.4375}, -- x beam4
			{-0.375, -0.5, 0.4375, 0.375, -0.375, 0.5}, -- x beam3
			{0.375, -0.5, -0.4375, 0.5, -0.375, 0.4375}, -- z beam2
			{-0.5, -0.5, -0.4375, -0.375, -0.375, 0.4375}, -- z beam1
			{0.375, -0.5, -0.5, 0.5, 0.375, -0.4375}, -- upright4
			{0.375, -0.5, 0.4375, 0.5, 0.375, 0.5}, -- upright3
			{-0.5, -0.5, -0.5, -0.375, 0.375, -0.4375}, -- upright2
			{-0.5, -0.5, 0.4375, -0.375, 0.375, 0.5}, -- upright1
		}
	},
	on_place = bridge_on_place,
})

minetest.register_craft({
	output = "ropes:wood_bridge 5",
	recipe = {
		{"group:stick", "stairs:slab_wood", "group:stick"},
		{"group:stick", "", "group:stick"},
		{"group:stick", "group:stick", "group:stick"},
	}
})

end

repo_name: korkut/MeseCraft

license: mit


code:
-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

if minetest.get_modpath("farming") then
-- this doesn't work reliably due to side effects of https://github.com/minetest/minetest/issues/5518
--	local old_def = minetest.registered_craftitems["farming:cotton"]
--	if old_def then
--		old_def.groups["thread"] = 1
--		minetest.override_item("farming:cotton", {
--			groups = old_def.groups
--		})
--	end
	minetest.register_craft({
		output = 'ropes:ropesegment',
		recipe = {
			{'farming:cotton','farming:cotton'},
			{'farming:cotton','farming:cotton'},
			{'farming:cotton','farming:cotton'},
		}
	})
end

if minetest.get_modpath("hemp") then
	minetest.register_craft({
		output = 'ropes:ropesegment',
		recipe = {
			{'hemp:hemp_rope'},
			{'hemp:hemp_rope'},
		}
	})
end

if minetest.get_modpath("cottages") then
	minetest.register_craft({
		output = 'ropes:ropesegment',
		recipe = {
			{'cottages:rope'},
			{'cottages:rope'},
		}
	})
end

minetest.register_craft({
	output = 'ropes:ropesegment',
	recipe = {
		{'group:thread','group:thread'},
		{'group:thread','group:thread'},
		{'group:thread','group:thread'},
	}
})

minetest.register_craftitem("ropes:ropesegment", {
	description = S("Rope Segment"),
	_doc_items_longdesc = ropes.doc.ropesegment_longdesc,
    _doc_items_usagehelp = ropes.doc.ropesegment_usage,
	groups = {vines = 1},
	inventory_image = "ropes_item.png",
})

local cotton_burn_time = 1
ropes.wood_burn_time = minetest.get_craft_result({method="fuel", width=1, items={ItemStack("default:wood")}}).time
ropes.rope_burn_time = cotton_burn_time * 6
local stick_burn_time = minetest.get_craft_result({method="fuel", width=1, items={ItemStack("default:stick")}}).time
ropes.ladder_burn_time = ropes.rope_burn_time * 2 + stick_burn_time * 3

minetest.register_craft({
	type = "fuel",
	recipe = "ropes:ropesegment",
	burntime = ropes.rope_burn_time,
})


code:
ropes.doc = {}

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

-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

ropes.doc.ropesegment_longdesc = S("Rope segments are bundles of fibre twisted into robust cables.")
ropes.doc.ropesegment_usage = S("This craft item is useful for creating rope ladders, or for spooling on wooden spindles to hang and climb upon.")

ropes.doc.ropeladder_longdesc = S("A hanging rope ladder that automatically extends downward.")
ropes.doc.ropeladder_usage = S("After a rope ladder is placed on a vertical wall it will begin extending downward until it reaches its maximum length (@1 meters). If the rope ladder is removed all of the ladder below the point of removal will disappear. A rope ladder can be severed partway down using an axe or similar tool, and the ladder below the point where it is cut will collapse. No rope is actually lost in the process, though, and if the uppermost section of the ladder is removed and replaced the ladder will re-extend to the same maximum length as before.", ropes.ropeLadderLength)

local rope_length_doc = S("Rope boxes have a certain amount of rope contained within them specified in the name of the node, and have a limit to how much rope they can support that depends on the material they're made of. The different lengths can be crafted by combining and splitting up rope boxes in the crafting grid. For example, you can craft a @1m rope box by putting a @2m rope box and a rope segment in the crafting grid, or a @3m rope box and two rope segments in the crafting grid. Two rope segments can be recovered by putting the @1m rope box in the crafting grid by itself.", ropes.ropeLength*3, ropes.ropeLength*2, ropes.ropeLength) .. "\n"

if ropes.woodRopeBoxMaxMultiple == 1 then
	rope_length_doc = rope_length_doc .. "\n" .. S("Wood") .. " " .. S("rope boxes can hold @1m of rope.", ropes.ropeLength)
elseif ropes.woodRopeBoxMaxMultiple > 1 then
	rope_length_doc = rope_length_doc .. "\n" .. S("Wood") .. " " .. S("rope boxes can hold rope lengths from @1m to @2m.", ropes.ropeLength, ropes.ropeLength*ropes.woodRopeBoxMaxMultiple)
end

if ropes.copperRopeBoxMaxMultiple == 1 then
	rope_length_doc = rope_length_doc .. "\n" .. S("Copper") .. " " .. S("rope boxes can hold @1m of rope.", ropes.ropeLength)
elseif ropes.copperRopeBoxMaxMultiple > 1 then
	rope_length_doc = rope_length_doc .. "\n" .. S("Copper") .. " " .. S("rope boxes can hold rope lengths from @1m to @2m.", ropes.ropeLength, ropes.ropeLength*ropes.copperRopeBoxMaxMultiple)
end

if ropes.steelRopeBoxMaxMultiple == 1 then
	rope_length_doc = rope_length_doc .. "\n" .. S("Steel") .. " " .. S("rope boxes can hold @1m of rope.", ropes.ropeLength)
elseif ropes.steelRopeBoxMaxMultiple > 1 then
	rope_length_doc = rope_length_doc .. "\n" .. S("Steel") .. " " .. S("rope boxes can hold rope lengths from @1m to @2m.", ropes.ropeLength, ropes.ropeLength*ropes.steelRopeBoxMaxMultiple)
end

ropes.doc.ropebox_longdesc = S("Ropes are hung by placing rope boxes, which automatically lower a rope of fixed length below them. They can be climbed and cut.")
ropes.doc.ropebox_usage = rope_length_doc .. "\n\n" ..
	S("When a rope box is placed the rope will immediately begin lowering from it at one meter per second. The rope will only descend when its end is in the vicinity of an active player, suspending its journey when no players are nearby, so a long descent may require a player to climb down the rope as it goes. If you are near the bottom end of a rope that's extending you'll be automatically carried down with it. The rope will stop when it encounters and obstruction, but will resume lowering if the obstruction is removed.") .. "\n\n" ..
	S("A rope can be severed midway using an axe or other similar tool. The section of rope below the cut will collapse and disappear, potentially causing players who were hanging on to it to fall. The remaining rope will not resume descent on its own, but the rope box at the top of the rope \"remembers\" how long the rope was and if it is deconstructed and replaced it will still have the same maximum length of rope as before - no rope is permanently lost when a rope is severed like this.")

if ropes.extending_ladder_enabled then
	ropes.doc.ladder_longdesc = S("A ladder for climbing. It can reach greater heights when placed against a supporting block.")
	ropes.doc.ladder_usagehelp = S("Right-clicking on a ladder with a stack of identical ladder items will automatically add new ladder segments to the top, provided it hasn't extended too far up beyond the last block behind it providing support.")
end

ropes.doc.wooden_bridge_longdesc = S("A wooden platform with support struts useful for bridging gaps.")
ropes.doc.wooden_bridge_usagehelp = S("This behaves like most structural blocks except in one circumstance: when placed on top of a block with buildable space on the side facing away from you, this block will not be built on top but instead will extend out from that far side of the target block. This allows a platform to be easily built that juts out away from the location you're standing on.")

doc.add_entry_alias("nodes", "ropes:ropeladder_top", "nodes", "ropes:ropeladder")
doc.add_entry_alias("nodes", "ropes:ropeladder_top", "nodes", "ropes:ropeladder_bottom")
doc.add_entry_alias("nodes", "ropes:ropeladder_top", "nodes", "ropes:ropeladder_falling")

doc.add_entry_alias("nodes", "ropes:rope", "nodes", "ropes:rope_bottom")
doc.add_entry_alias("nodes", "ropes:rope", "nodes", "ropes:rope_top")


code:
local modpath = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(modpath.."/intllib.lua")

if ropes.extending_ladder_enabled then

local wood_recipe = {
		{"group:stick", "group:stick", "group:stick"},
		{"group:stick", "", "group:stick"},
		{"group:stick", "", "group:stick"},
	}
local wood_name = S("Wooden Extendable Ladder")

local steel_recipe = {
		{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
		{"default:steel_ingot", "", "default:steel_ingot"},
		{"default:steel_ingot", "", "default:steel_ingot"},
	}
local steel_name = S("Steel Extendable Ladder")

if ropes.replace_default_ladders then

minetest.unregister_item("default:ladder_wood")
minetest.unregister_item("default:ladder_steel")
minetest.clear_craft({output = "default:ladder_wood"})
minetest.clear_craft({output = "default:ladder_steel"})

local wallmounted_to_facedir =
{[0] = 15, -- ceiling
[1] = 13, -- floor
[2] = 1, -- +X
[3] = 3, -- -X
[4] = 0, -- +Z
[5] = 2, -- -Z
}

minetest.register_lbm({
    label = "Switch from wallmounted default ladders to rope mod extending ladders",
    name = "ropes:wallmounted_ladder_to_facedir_ladder",
    nodenames = {"default:ladder_wood", "default:ladder_steel"},
    run_at_every_load = false,
    action = function(pos, node)
		local new_node = {param2 = wallmounted_to_facedir[node.param2]}
		if (node.name == "default:ladder_wood") then
			new_node.name = "ropes:ladder_wood"
		else
			new_node.name = "ropes:ladder_steel"
		end
		minetest.set_node(pos, new_node)
	end,
})

wood_recipe = {
		{"group:stick", "", "group:stick"},
		{"group:stick", "group:stick", "group:stick"},
		{"group:stick", "", "group:stick"},
	}
wood_name = S("Wooden Ladder")

steel_recipe = {
		{'default:steel_ingot', '', 'default:steel_ingot'},
		{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
		{'default:steel_ingot', '', 'default:steel_ingot'},
	}
steel_name = S("Steel Ladder")

end

minetest.register_craft({
	output = "ropes:ladder_wood 5",
	recipe = wood_recipe,
})

minetest.register_craft({
	output = 'ropes:ladder_steel 15',
	recipe = steel_recipe,
})

local ladder_extender = function(pos, node, clicker, itemstack, pointed_thing, ladder_node, standing_limit)
	-- on_rightclick can be called by other mods, make sure we have all the parameters we need
	if pointed_thing == nil or itemstack == nil then
		return itemstack
	end

	local clicked_stack = ItemStack(itemstack)

	-- true if we're pointing up at the ladder from below and there's a buildable space below it
	-- this check allows us to extend ladders downward
	local pointing_directly_below =
		pointed_thing.above.x == pos.x and
		pointed_thing.above.z == pos.z and
		pointed_thing.above.y == pos.y - 1 and
		minetest.registered_nodes[minetest.get_node(pointed_thing.above).name].buildable_to

	if clicked_stack:get_name() == ladder_node and not pointing_directly_below then
		local param2 = minetest.get_node(pos).param2
		local dir = minetest.facedir_to_dir(param2)
		local scan_limit = pos.y + 6 -- Only add ladder segments up to five nodes above the one clicked on
		pos.y = pos.y + 1
		while pos.y < scan_limit and minetest.get_node(pos).name == ladder_node do
			param2 = minetest.get_node(pos).param2
			pos.y = pos.y + 1
		end
		if pos.y < scan_limit and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then

			-- scan downward behind the ladder to find support
			local behind_pos = vector.add(pos, minetest.facedir_to_dir(param2))
			local target_height = pos.y - standing_limit - 1
			while behind_pos.y > target_height and minetest.registered_nodes[minetest.get_node(behind_pos).name].buildable_to do
				behind_pos.y = behind_pos.y - 1
			end

			-- If there's enough support, build a new ladder segment
			if behind_pos.y > target_height then
				if minetest.is_protected(pos, clicker:get_player_name()) then
					minetest.record_protection_violation(clicker:get_player_name())
				else
					minetest.set_node(pos, {name=ladder_node, param2=param2})
					if not minetest.settings:get_bool("creative_mode") then
						clicked_stack:take_item(1)
					end
				end
			end
		end
	elseif clicked_stack:get_definition().type == "node" then
		return minetest.item_place_node(itemstack, clicker, pointed_thing)
	end
	return clicked_stack
end

minetest.register_node("ropes:ladder_wood", {
	description = wood_name,
	_doc_items_longdesc = ropes.doc.ladder_longdesc,
	_doc_items_usagehelp = ropes.doc.ladder_usagehelp,
	tiles = {"default_wood.png","default_wood.png","default_wood.png^[transformR270","default_wood.png^[transformR270","default_ladder_wood.png"},
	inventory_image = "default_ladder_wood.png",
	wield_image = "default_ladder_wood.png",
	paramtype = "light",
	paramtype2 = "facedir",
	sunlight_propagates = true,
	walkable = false,
	climbable = true,
	is_ground_content = false,
	drawtype = "nodebox",
	paramtype = "light",
	node_box = {
		type = "fixed",
		fixed = {
			{-0.375, -0.5, 0.375, -0.25, 0.5, 0.5}, -- Upright1
			{0.25, -0.5, 0.375, 0.375, 0.5, 0.5}, -- Upright2
			{-0.4375, 0.3125, 0.4375, 0.4375, 0.4375, 0.5}, -- Rung_4
			{-0.4375, -0.1875, 0.4375, 0.4375, -0.0625, 0.5}, -- Rung_2
			{-0.4375, -0.4375, 0.4375, 0.4375, -0.3125, 0.5}, -- Rung_1
			{-0.4375, 0.0625, 0.4375, 0.4375, 0.1875, 0.5}, -- Rung_3
		}
	},
	groups = {choppy = 2, oddly_breakable_by_hand = 3, flammable = 2, flow_through = 1},
	sounds = default.node_sound_wood_defaults(),
	on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
		return ladder_extender(pos, node, clicker, itemstack, pointed_thing, "ropes:ladder_wood", ropes.extending_wood_ladder_limit)
	end,
})

minetest.register_node("ropes:ladder_steel", {
	description = steel_name,
	_doc_items_longdesc = ropes.doc.ladder_longdesc,
	_doc_items_usagehelp = ropes.doc.ladder_usagehelp,
	tiles = {"default_steel_block.png","default_steel_block.png","default_steel_block.png","default_steel_block.png","default_ladder_steel.png"},
	inventory_image = "default_ladder_steel.png",
	wield_image = "default_ladder_steel.png",
	paramtype = "light",
	paramtype2 = "facedir",
	sunlight_propagates = true,
	walkable = false,
	climbable = true,
	is_ground_content = false,
	drawtype = "nodebox",
	node_box = {
		type = "fixed",
		fixed = {
			{-0.4375, -0.5, 0.3125, -0.25, 0.5, 0.5}, -- Upright1
			{0.25, -0.5, 0.3125, 0.4375, 0.5, 0.5}, -- Upright2
			{-0.25, 0.3125, 0.375, 0.25, 0.4375, 0.5}, -- Rung_4
			{-0.25, -0.1875, 0.375, 0.25, -0.0625, 0.5}, -- Rung_2
			{-0.25, -0.4375, 0.375, 0.25, -0.3125, 0.5}, -- Rung_1
			{-0.25, 0.0625, 0.375, 0.25, 0.1875, 0.5}, -- Rung_3
		}
	},
	groups = {cracky = 2, flow_through = 1},
	sounds = default.node_sound_metal_defaults(),
	on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
		return ladder_extender(pos, node, clicker, itemstack, pointed_thing, "ropes:ladder_steel", ropes.extending_steel_ladder_limit)
	end,
})

else

-- Table of possible wallmounted values
local facedir_to_wallmounted = {
	4, -- +Z
	2, -- +X
	5, -- -Z
	3, -- -X
	1, -- -Y
	0, -- +Y
}
-- Mapping from facedir value to index in facedir_to_dir.
local facedir_to_wallmounted_map = {
	[0]=1, 2, 3, 4,
	5, 2, 6, 4,
	6, 2, 5, 4,
	1, 5, 3, 6,
	1, 6, 3, 5,
	1, 4, 3, 2,
}

minetest.register_lbm({
    label = "Switch from ropes ladders to wallmounted default ladders",
    name = "ropes:facedir_ladder_to_wallmounted_ladder",
    nodenames = {"ropes:ladder_wood", "ropes:ladder_steel"},
    run_at_every_load = false,
    action = function(pos, node)
		local new_node = {param2 = facedir_to_wallmounted[facedir_to_wallmounted_map[node.param2 % 32]]}
		if (node.name == "ropes:ladder_wood") then
			new_node.name = "default:ladder_wood"
		else
			new_node.name = "default:ladder_steel"
		end
		minetest.set_node(pos, new_node)
	end,
})

end


code:
ropes.make_rope_on_timer = function(rope_node_name)
	return function(pos, elapsed)
		local currentend = minetest.get_node(pos)
		local currentmeta = minetest.get_meta(pos)
		local currentlength = currentmeta:get_int("length_remaining")
		local placer_name = currentmeta:get_string("placer")
		local newpos = {x=pos.x, y=pos.y-1, z=pos.z}
		local newnode = minetest.get_node(newpos)
		local oldnode = minetest.get_node(pos)
		if currentlength > 1 and (not minetest.is_protected(newpos, placer_name)
		or minetest.check_player_privs(placer_name, "protection_bypass")) then
			if  newnode.name == "air" then
				minetest.add_node(newpos, {name=currentend.name, param2=oldnode.param2})
				local newmeta = minetest.get_meta(newpos)
				newmeta:set_int("length_remaining", currentlength-1)
				newmeta:set_string("placer", placer_name)
				minetest.set_node(pos, {name=rope_node_name, param2=oldnode.param2})
				ropes.move_players_down(pos, 1)
			else
				local timer = minetest.get_node_timer( pos )
				timer:start( 1 )
			end
		end
	end
end

local data = {}
local c_air = minetest.get_content_id("air")

ropes.destroy_rope = function(pos, nodes)
	local top = pos.y
	local bottom = pos.y-15
	local voxel_manip = minetest.get_voxel_manip()

	local finished = false
	local ids_to_destroy = {}
	for _, node in pairs(nodes) do
		ids_to_destroy[minetest.get_content_id(node)] = true
	end

	while not finished do
		local emin, emax = voxel_manip:read_from_map({x=pos.x, y=bottom, z=pos.z}, {x=pos.x, y=top, z=pos.z})
		voxel_manip:get_data(data)
		local voxel_area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
		bottom = emin.y
		for y = top, bottom, -1 do
			local index = voxel_area:index(pos.x, y, pos.z)
			if ids_to_destroy[data[index]] then
				data[index] = c_air
			else
				finished = true
				break
			end
		end
		voxel_manip:set_data(data)
		voxel_manip:write_to_map()
		voxel_manip:update_map()
		top = bottom - 1
		bottom = bottom - 15
	end
end

ropes.hanging_after_destruct = function(pos, top_node, middle_node, bottom_node)
	local node = minetest.get_node(pos)
	if node.name == top_node or node.name == middle_node or node.name == bottom_node then
		return -- this was done by another ladder or rope node changing this one, don't react
	end

	pos.y = pos.y + 1 -- one up
	local node_above = minetest.get_node(pos)
	if node_above.name == middle_node then
		minetest.swap_node(pos, {name=bottom_node, param2=node_above.param2})
	end

	pos.y = pos.y - 2 -- one down
	local node_below = minetest.get_node(pos)
	if node_below.name == middle_node then
		ropes.destroy_rope(pos, {middle_node, bottom_node})
	elseif node_below.name == bottom_node then
		minetest.swap_node(pos, {name="air"})
	end
end

ropes.move_players_down = function(pos, radius)
	local all_objects = minetest.get_objects_inside_radius({x=pos.x, y=pos.y+radius, z=pos.z}, radius)
	local players = {}
	local _,obj
	for _,obj in pairs(all_objects) do
		if obj:is_player() then
			local obj_pos = obj:getpos()
			if math.abs(obj_pos.x-pos.x) < 0.5 and math.abs(obj_pos.z-pos.z) < 0.5 then
				obj:moveto({x=obj_pos.x, y=obj_pos.y-1, z=obj_pos.z}, true)
			end
		end
	end
end


code:
ropes = {
  name = 'ropes',
}

-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

ropes.ropeLength = tonumber(minetest.settings:get("ropes_rope_length")) or 50
ropes.woodRopeBoxMaxMultiple = tonumber(minetest.settings:get("ropes_wood_rope_box_max_multiple")) or 2
ropes.copperRopeBoxMaxMultiple = tonumber(minetest.settings:get("ropes_copper_rope_box_max_multiple")) or 5
ropes.steelRopeBoxMaxMultiple = tonumber(minetest.settings:get("ropes_steel_rope_box_max_multiple")) or 9
ropes.create_all_definitions = minetest.settings:get_bool("ropes_create_all_definitions")

ropes.ropeLadderLength = tonumber(minetest.settings:get("ropes_rope_ladder_length")) or 50

ropes.extending_ladder_enabled = minetest.settings:get_bool("ropes_extending_ladder_enabled")
if ropes.extending_ladder_enabled == nil then
	ropes.extending_ladder_enabled = true
end
ropes.replace_default_ladders = minetest.settings:get_bool("ropes_replace_default_ladders")

ropes.extending_wood_ladder_limit = tonumber(minetest.settings:get("ropes_extending_wood_ladder_limit")) or 5
ropes.extending_steel_ladder_limit = tonumber(minetest.settings:get("ropes_extending_steel_ladder_limit")) or 15

ropes.bridges_enabled = minetest.settings:get_bool("ropes_bridges_enabled")
if ropes.bridges_enabled == nil then
	ropes.bridges_enabled = true
end

dofile( MP .. "/doc.lua" )
dofile( MP .. "/functions.lua" )
dofile( MP .. "/crafts.lua" )
dofile( MP .. "/ropeboxes.lua" )
dofile( MP .. "/ropeladder.lua" )
dofile( MP .. "/extendingladder.lua" )
dofile( MP .. "/bridge.lua" )
dofile( MP .. "/loot.lua" )

for i=1,5 do
	minetest.register_alias(string.format("vines:%irope_block", i), string.format("ropes:%irope_block", i))
end
minetest.register_alias("vines:rope", "ropes:rope")
minetest.register_alias("vines:rope_bottom", "ropes:rope_bottom")
minetest.register_alias("vines:rope_end", "ropes:rope_bottom")
minetest.register_alias("vines:rope_top", "ropes:rope_top")
minetest.register_alias("vines:ropeladder_top", "ropes:ropeladder_top")
minetest.register_alias("vines:ropeladder", "ropes:ropeladder")
minetest.register_alias("vines:ropeladder_bottom", "ropes:ropeladder_bottom")
minetest.register_alias("vines:ropeladder_falling", "ropes:ropeladder_falling")
minetest.register_alias("vines:rope_block", "ropes:steel5rope_block")
for i=1,9 do
	minetest.register_alias(string.format("ropes:%irope_block", i), string.format("ropes:steel%irope_block", i))
end
minetest.register_alias("castle:ropes", "ropes:rope")
minetest.register_alias("castle:ropebox", "ropes:steel1rope_block")
minetest.register_alias("castle:box_rope", "ropes:rope")

print("[Ropes] Loaded!")


code:
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.

-- Get the latest version of this file at:
--   https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua

local function format(str, ...)
	local args = { ... }
	local function repl(escape, open, num, close)
		if escape == "" then
			local replacement = tostring(args[tonumber(num)])
			if open == "" then
				replacement = replacement..close
			end
			return replacement
		else
			return "@"..open..num..close
		end
	end
	return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end

local gettext, ngettext
if minetest.get_modpath("intllib") then
	if intllib.make_gettext_pair then
		-- New method using gettext.
		gettext, ngettext = intllib.make_gettext_pair()
	else
		-- Old method using text files.
		gettext = intllib.Getter()
	end
end

-- Fill in missing functions.

gettext = gettext or function(msgid, ...)
	return format(msgid, ...)
end

ngettext = ngettext or function(msgid, msgid_plural, n, ...)
	return format(n==1 and msgid or msgid_plural, ...)
end

return gettext, ngettext


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-28 16:30-0600\n"
"PO-Revision-Date: 2018-10-27 11:26+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.11\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: bridge.lua:49
msgid "Wooden Bridge"
msgstr ""

#: crafts.lua:54
msgid "Rope Segment"
msgstr "Segmento de cuerda"

#: doc.lua:11
msgid "Rope segments are bundles of fibre twisted into robust cables."
msgstr ""
"Los segmentos de cable son haces de fibras trenzadas en cables robustos."

#: doc.lua:12
msgid ""
"This craft item is useful for creating rope ladders, or for spooling on "
"wooden spindles to hang and climb upon."
msgstr ""
"Esta objeto es útil para crear escaleras de cuerda, o para enrollar en "
"husillos de madera para colgar y trepar."

#: doc.lua:14
msgid "A hanging rope ladder that automatically extends downward."
msgstr ""
"Una escalera de cuerda colgante que se extiende automáticamente hacia abajo."

#: doc.lua:15
msgid ""
"After a rope ladder is placed on a vertical wall it will begin extending "
"downward until it reaches its maximum length (@1 meters). If the rope ladder "
"is removed all of the ladder below the point of removal will disappear. A "
"rope ladder can be severed partway down using an axe or similar tool, and "
"the ladder below the point where it is cut will collapse. No rope is "
"actually lost in the process, though, and if the uppermost section of the "
"ladder is removed and replaced the ladder will re-extend to the same maximum "
"length as before."
msgstr ""
"Después de colocar una escalera de cuerda en una pared vertical, comenzará a "
"extenderse hacia abajo hasta que alcance su longitud máxima (@1 metro). Si "
"se retira la escalera de cuerda, desaparecerá toda la escalera por debajo "
"del punto de extracción. Una escalera de cuerda puede ser cortada hasta la "
"mitad usando un hacha o una herramienta similar, y la escalera por debajo "
"del punto donde es cortada colapsará. Sin embargo, no se pierde ninguna "
"cuerda en el proceso, y si la sección superior de la escalera se retira y se "
"reemplaza, la escalera se volverá a extender a la misma longitud máxima que "
"antes."

#: doc.lua:17
msgid ""
"Rope boxes have a certain amount of rope contained within them specified in "
"the name of the node, and have a limit to how much rope they can support "
"that depends on the material they're made of. The different lengths can be "
"crafted by combining and splitting up rope boxes in the crafting grid. For "
"example, you can craft a @1m rope box by putting a @2m rope box and a rope "
"segment in the crafting grid, or a @3m rope box and two rope segments in the "
"crafting grid. Two rope segments can be recovered by putting the @1m rope "
"box in the crafting grid by itself."
msgstr ""
"Las cajas de cuerdas tienen una cierta cantidad de cuerda contenida dentro "
"de ellas especificada en el nombre del nodo, y tienen un límite en la "
"cantidad de cuerda que pueden soportar que depende del material del que "
"están hechas. Las diferentes longitudes se pueden realizar combinando y "
"dividiendo las cajas de cuerda en la rejilla de elaboración. Por ejemplo, "
"puedes crear una caja de cuerda de @1m poniendo una caja de cuerda de @2m y "
"un segmento de cuerda en la rejilla de artesanía, o una caja de cuerda de "
"@3m y dos segmentos de cuerda en la rejilla de artesanía. Se pueden "
"recuperar dos segmentos de cable colocando solo la caja de cable de @1m en "
"la rejilla de fabricación."

#: doc.lua:20
#: doc.lua:22
#: ropeboxes.lua:321
msgid "Wood"
msgstr "madera"

#: doc.lua:20
#: doc.lua:26
#: doc.lua:32
msgid "rope boxes can hold @1m of rope."
msgstr "Las cajas de cuerdas pueden mantener @1m de cuerda."

#: doc.lua:22
#: doc.lua:28
#: doc.lua:34
msgid "rope boxes can hold rope lengths from @1m to @2m."
msgstr "Las cajas de cuerda pueden contener longitudes de cuerda de @1m a @2m."

#: doc.lua:26
#: doc.lua:28
#: ropeboxes.lua:338
msgid "Copper"
msgstr "cobre"

#: doc.lua:32
#: doc.lua:34
#: ropeboxes.lua:355
msgid "Steel"
msgstr "acero"

#: doc.lua:37
msgid ""
"Ropes are hung by placing rope boxes, which automatically lower a rope of "
"fixed length below them. They can be climbed and cut."
msgstr ""
"Las cuerdas se cuelgan colocando cajas de cuerda, que bajan automáticamente "
"una cuerda de longitud fija por debajo de ellas. Se pueden escalar y cortar."

#: doc.lua:39
msgid ""
"When a rope box is placed the rope will immediately begin lowering from it "
"at one meter per second. The rope will only descend when its end is in the "
"vicinity of an active player, suspending its journey when no players are "
"nearby, so a long descent may require a player to climb down the rope as it "
"goes. If you are near the bottom end of a rope that's extending you'll be "
"automatically carried down with it. The rope will stop when it encounters "
"and obstruction, but will resume lowering if the obstruction is removed."
msgstr ""
"Cuando se coloca una caja de cuerda, la cuerda comienza a descender "
"inmediatamente a un metro por segundo. La cuerda sólo descenderá cuando su "
"final esté cerca de un jugador activo, suspendiendo su viaje cuando no haya "
"jugadores cerca, por lo que un largo descenso puede requerir que el jugador "
"baje por la cuerda a medida que avanza. Si estás cerca del extremo inferior "
"de una cuerda que se está extendiendo, serás arrastrado automáticamente "
"hacia abajo con ella. La cuerda se detendrá cuando se encuentre con una "
"obstrucción, pero volverá a bajar si se retira la obstrucción."

#: doc.lua:40
msgid ""
"A rope can be severed midway using an axe or other similar tool. The section "
"of rope below the cut will collapse and disappear, potentially causing "
"players who were hanging on to it to fall. The remaining rope will not "
"resume descent on its own, but the rope box at the top of the rope "
"\"remembers\" how long the rope was and if it is deconstructed and replaced "
"it will still have the same maximum length of rope as before - no rope is "
"permanently lost when a rope is severed like this."
msgstr ""
"Una cuerda puede ser cortada a mitad de camino usando un hacha u otra "
"herramienta similar. La sección de la cuerda debajo del corte se colapsará y "
"desaparecerá, lo que puede causar que los jugadores que estaban colgados de "
"ella se caigan. El resto de la cuerda no volverá a descender por sí sola, "
"pero la caja de la cuerda en la parte superior de la cuerda \"recuerda\" la "
"longitud de la cuerda y si es deconstruida y reemplazada tendrá la misma "
"longitud máxima de cuerda que antes - ninguna cuerda se pierde "
"permanentemente cuando una cuerda es cortada de esta manera."

#: doc.lua:43
msgid ""
"A ladder for climbing. It can reach greater heights when placed against a "
"supporting block."
msgstr ""

#: doc.lua:44
msgid ""
"Right-clicking on a ladder with a stack of identical ladder items will "
"automatically add new ladder segments to the top, provided it hasn't "
"extended too far up beyond the last block behind it providing support."
msgstr ""

#: doc.lua:47
msgid "A wooden platform with support struts useful for bridging gaps."
msgstr ""

#: doc.lua:48
msgid ""
"This behaves like most structural blocks except in one circumstance: when "
"placed on top of a block with buildable space on the side facing away from "
"you, this block will not be built on top but instead will extend out from "
"that far side of the target block. This allows a platform to be easily built "
"that juts out away from the location you're standing on."
msgstr ""

#: extendingladder.lua:11
msgid "Wooden Ladder"
msgstr ""

#: extendingladder.lua:18
msgid "Steel Ladder"
msgstr ""

#: extendingladder.lua:57
msgid "Wooden Extendable Ladder"
msgstr ""

#: extendingladder.lua:64
msgid "Steel Extendable Ladder"
msgstr ""

#: ropeboxes.lua:121
msgid "@1 Ropebox @2m"
msgstr "Caja de cuerda de @1 de @2m"

#: ropeboxes.lua:229
#: ropeboxes.lua:264
msgid "Rope"
msgstr "Cuerda"

#: ropeladder.lua:27
#: ropeladder.lua:89
#: ropeladder.lua:119
#: ropeladder.lua:153
msgid "Rope Ladder"
msgstr "Escalera de cuerda"


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-28 16:30-0600\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: bridge.lua:49
msgid "Wooden Bridge"
msgstr ""

#: crafts.lua:54
msgid "Rope Segment"
msgstr ""

#: doc.lua:11
msgid "Rope segments are bundles of fibre twisted into robust cables."
msgstr ""

#: doc.lua:12
msgid ""
"This craft item is useful for creating rope ladders, or for spooling on "
"wooden spindles to hang and climb upon."
msgstr ""

#: doc.lua:14
msgid "A hanging rope ladder that automatically extends downward."
msgstr ""

#: doc.lua:15
msgid ""
"After a rope ladder is placed on a vertical wall it will begin extending "
"downward until it reaches its maximum length (@1 meters). If the rope ladder "
"is removed all of the ladder below the point of removal will disappear. A "
"rope ladder can be severed partway down using an axe or similar tool, and "
"the ladder below the point where it is cut will collapse. No rope is "
"actually lost in the process, though, and if the uppermost section of the "
"ladder is removed and replaced the ladder will re-extend to the same maximum "
"length as before."
msgstr ""

#: doc.lua:17
msgid ""
"Rope boxes have a certain amount of rope contained within them specified in "
"the name of the node, and have a limit to how much rope they can support "
"that depends on the material they're made of. The different lengths can be "
"crafted by combining and splitting up rope boxes in the crafting grid. For "
"example, you can craft a @1m rope box by putting a @2m rope box and a rope "
"segment in the crafting grid, or a @3m rope box and two rope segments in the "
"crafting grid. Two rope segments can be recovered by putting the @1m rope "
"box in the crafting grid by itself."
msgstr ""

#: doc.lua:20
#: doc.lua:22
#: ropeboxes.lua:321
msgid "Wood"
msgstr ""

#: doc.lua:20
#: doc.lua:26
#: doc.lua:32
msgid "rope boxes can hold @1m of rope."
msgstr ""

#: doc.lua:22
#: doc.lua:28
#: doc.lua:34
msgid "rope boxes can hold rope lengths from @1m to @2m."
msgstr ""

#: doc.lua:26
#: doc.lua:28
#: ropeboxes.lua:338
msgid "Copper"
msgstr ""

#: doc.lua:32
#: doc.lua:34
#: ropeboxes.lua:355
msgid "Steel"
msgstr ""

#: doc.lua:37
msgid ""
"Ropes are hung by placing rope boxes, which automatically lower a rope of "
"fixed length below them. They can be climbed and cut."
msgstr ""

#: doc.lua:39
msgid ""
"When a rope box is placed the rope will immediately begin lowering from it "
"at one meter per second. The rope will only descend when its end is in the "
"vicinity of an active player, suspending its journey when no players are "
"nearby, so a long descent may require a player to climb down the rope as it "
"goes. If you are near the bottom end of a rope that's extending you'll be "
"automatically carried down with it. The rope will stop when it encounters "
"and obstruction, but will resume lowering if the obstruction is removed."
msgstr ""

#: doc.lua:40
msgid ""
"A rope can be severed midway using an axe or other similar tool. The section "
"of rope below the cut will collapse and disappear, potentially causing "
"players who were hanging on to it to fall. The remaining rope will not "
"resume descent on its own, but the rope box at the top of the rope "
"\"remembers\" how long the rope was and if it is deconstructed and replaced "
"it will still have the same maximum length of rope as before - no rope is "
"permanently lost when a rope is severed like this."
msgstr ""

#: doc.lua:43
msgid ""
"A ladder for climbing. It can reach greater heights when placed against a "
"supporting block."
msgstr ""

#: doc.lua:44
msgid ""
"Right-clicking on a ladder with a stack of identical ladder items will "
"automatically add new ladder segments to the top, provided it hasn't "
"extended too far up beyond the last block behind it providing support."
msgstr ""

#: doc.lua:47
msgid "A wooden platform with support struts useful for bridging gaps."
msgstr ""

#: doc.lua:48
msgid ""
"This behaves like most structural blocks except in one circumstance: when "
"placed on top of a block with buildable space on the side facing away from "
"you, this block will not be built on top but instead will extend out from "
"that far side of the target block. This allows a platform to be easily built "
"that juts out away from the location you're standing on."
msgstr ""

#: extendingladder.lua:11
msgid "Wooden Ladder"
msgstr ""

#: extendingladder.lua:18
msgid "Steel Ladder"
msgstr ""

#: extendingladder.lua:57
msgid "Wooden Extendable Ladder"
msgstr ""

#: extendingladder.lua:64
msgid "Steel Extendable Ladder"
msgstr ""

#: ropeboxes.lua:121
msgid "@1 Ropebox @2m"
msgstr ""

#: ropeboxes.lua:229
#: ropeboxes.lua:264
msgid "Rope"
msgstr ""

#: ropeladder.lua:27
#: ropeladder.lua:89
#: ropeladder.lua:119
#: ropeladder.lua:153
msgid "Rope Ladder"
msgstr ""


code:
@echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
cd ..
set LIST=
for /r %%X in (*.lua) do set LIST=!LIST! %%X
..\intllib\tools\xgettext.bat %LIST%


code:
if not minetest.get_modpath("loot") then
	return
end

loot.register_loot({
	weights = { generic = 300 },
	payload = {
		stack = ItemStack("ropes:ropesegment"),
		min_size = 1,
		max_size = 50,
	},
})

if ropes.ropeLadderLength > 0 then
loot.register_loot({
	weights = { generic = 150 },
	payload = {
		stack = ItemStack("ropes:ropeladder_top"),
		min_size = 1,
		max_size = 20,
	},
})
end

if ropes.woodRopeBoxMaxMultiple > 0 then
loot.register_loot({
	weights = { generic = 100 },
	payload = {
		stack = ItemStack("ropes:wood1rope_block"),
		min_size = 1,
		max_size = 20,
	},
})
end

if ropes.copperRopeBoxMaxMultiple > 0 then
loot.register_loot({
	weights = { generic = 75 },
	payload = {
		stack = ItemStack("ropes:copper1rope_block"),
		min_size = 1,
		max_size = 15,
	},
})
end

if ropes.steelRopeBoxMaxMultiple > 0 then
loot.register_loot({
	weights = { generic = 50 },
	payload = {
		stack = ItemStack("ropes:steel1rope_block"),
		min_size = 1,
		max_size = 10,
	},
})
end


code:
name = ropes
description = Adds rope boxes of various lengths and also rope ladders.
depends = default
optional_depends = farming, vines, doc, intllib, loot, hemp, cottages
author = FaceDeer
title = Ropes


code:
if ropes.ropeLadderLength == 0 and not ropes.create_all_definitions then
	return
end

-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

if ropes.ropeLadderLength > 0 then
	minetest.register_craft({
		output = "ropes:ropeladder_top",
		recipe =  {
			{'','group:stick',''},
			{'group:vines','group:stick','group:vines'},
			{'','group:stick',''},
		}
	})
end

minetest.register_craft({
	type = "fuel",
	recipe = "ropes:ropeladder_top",
	burntime = ropes.ladder_burn_time,
})

local rope_ladder_top_def = {
	description = S("Rope Ladder"),
	_doc_items_longdesc = ropes.doc.ropeladder_longdesc,
    _doc_items_usagehelp = ropes.doc.ropeladder_usage,
	drawtype = "signlike",
	tiles = {"default_ladder_wood.png^ropes_ropeladder_top.png"},
	is_ground_content = false,
	inventory_image = "default_ladder_wood.png^ropes_ropeladder_top.png",
	wield_image = "default_ladder_wood.png^ropes_ropeladder_top.png",
	paramtype = "light",
	paramtype2 = "wallmounted",
	walkable = false,
	climbable = true,
	sunlight_propagates = true,
	selection_box = {
		type = "wallmounted",
		--wall_top = = <default>
		--wall_bottom = = <default>
		--wall_side = = <default>

	},
	groups = { choppy=2, oddly_breakable_by_hand=1,flammable=2},
	sounds = default.node_sound_wood_defaults(),

	on_place = function(itemstack, placer, pointed_thing)
		if pointed_thing.type == "node" then
			local target_node = minetest.get_node(pointed_thing.under)
			local target_def = minetest.registered_nodes[target_node.name]
			if target_def.walkable == false then
				return itemstack
			end
		end
		return minetest.item_place(itemstack, placer, pointed_thing)
	end,

	after_place_node = function(pos, placer)
		local pos_below = {x=pos.x, y=pos.y-1, z=pos.z}
		local node_below = minetest.get_node(pos_below)
		local this_node = minetest.get_node(pos)
		local placer_name = placer:get_player_name()
		-- param2 holds the facing direction of this node. If it's 0 or 1 the node is "flat" and we don't want the ladder to extend.
		if node_below.name == "air" and this_node.param2 > 1
		  and (not minetest.is_protected(pos_below, placer_name)
		  or minetest.check_player_privs(placer_name, "protection_bypass")) then
			minetest.add_node(pos_below, {name="ropes:ropeladder_bottom", param2=this_node.param2})
			local meta = minetest.get_meta(pos_below)
			meta:set_int("length_remaining", ropes.ropeLadderLength)
			meta:set_string("placer", placer_name)
		end
	end,
	after_destruct = function(pos)
		local pos_below = {x=pos.x, y=pos.y-1, z=pos.z}
		ropes.destroy_rope(pos_below, {"ropes:ropeladder", "ropes:ropeladder_bottom", "ropes:ropeladder_falling"})
	end,
}

if ropes.ropeLadderLength == 0 then
	rope_ladder_top_def.groups.not_in_creative_inventory = 1
end

minetest.register_node("ropes:ropeladder_top", rope_ladder_top_def)

minetest.register_node("ropes:ropeladder", {
	description = S("Rope Ladder"),
	_doc_items_create_entry = false,
	drop = "",
	drawtype = "signlike",
	tiles = {"default_ladder_wood.png^ropes_ropeladder.png"},
	is_ground_content = false,
	inventory_image = "default_ladder_wood.png^ropes_ropeladder.png",
	wield_image = "default_ladder_wood.png^ropes_ropeladder.png",
	paramtype = "light",
	paramtype2 = "wallmounted",
	walkable = false,
	climbable = true,
	sunlight_propagates = true,
	selection_box = {
		type = "wallmounted",
		--wall_top = = <default>
		--wall_bottom = = <default>
		--wall_side = = <default>
	},
	groups = {choppy=2, flammable=2, not_in_creative_inventory=1},
	sounds = default.node_sound_wood_defaults(),

	after_destruct = function(pos)
		ropes.hanging_after_destruct(pos, "ropes:ropeladder_falling", "ropes:ropeladder", "ropes:ropeladder_bottom")
	end,
})

local ladder_extender = ropes.make_rope_on_timer("ropes:ropeladder")

minetest.register_node("ropes:ropeladder_bottom", {
	description = S("Rope Ladder"),
	_doc_items_create_entry = false,
	drop = "",
	drawtype = "signlike",
	tiles = {"default_ladder_wood.png^ropes_ropeladder_bottom.png"},
	is_ground_content = false,
	inventory_image = "default_ladder_wood.png^ropes_ropeladder_bottom.png",
	wield_image = "default_ladder_wood.png^ropes_ropeladder_bottom.png",
	paramtype = "light",
	paramtype2 = "wallmounted",
	walkable = false,
	climbable = true,
	sunlight_propagates = true,
	selection_box = {
		type = "wallmounted",
		--wall_top = = <default>
		--wall_bottom = = <default>
		--wall_side = = <default>

	},
	groups = {choppy=2, flammable=2, not_in_creative_inventory=1},
	sounds = default.node_sound_wood_defaults(),
	on_construct = function( pos )
		local timer = minetest.get_node_timer( pos )
		timer:start( 1 )
	end,
	on_timer = ladder_extender,

	after_destruct = function(pos)
		ropes.hanging_after_destruct(pos, "ropes:ropeladder_falling", "ropes:ropeladder", "ropes:ropeladder_bottom")
	end,
})

minetest.register_node("ropes:ropeladder_falling", {
	description = S("Rope Ladder"),
	_doc_items_create_entry = false,
	drop = "",
	drawtype = "signlike",
	tiles = {"default_ladder_wood.png^ropes_ropeladder.png"},
	is_ground_content = false,
	inventory_image = "default_ladder_wood.png^ropes_ropeladder.png",
	wield_image = "default_ladder_wood.png^ropes_ropeladder.png",
	paramtype = "light",
	paramtype2 = "wallmounted",
	walkable = false,
	climbable = true,
	sunlight_propagates = true,
	selection_box = {
		type = "wallmounted",
		--wall_top = = <default>
		--wall_bottom = = <default>
		--wall_side = = <default>

	},
	groups = {flammable=2, not_in_creative_inventory=1},
	sounds = default.node_sound_wood_defaults(),
	on_construct = function( pos )
		local timer = minetest.get_node_timer( pos )
		timer:start( 1 )
	end,
	on_timer = function( pos, elapsed )
		local pos_below = {x=pos.x, y=pos.y-1, z=pos.z}
		local node_below = minetest.get_node(pos_below)

		if (node_below.name ~= "ignore") then
			ropes.destroy_rope(pos_below, {'ropes:ropeladder', 'ropes:ropeladder_bottom', 'ropes:ropeladder_falling'})
			minetest.swap_node(pos, {name="air"})
		else
			local timer = minetest.get_node_timer( pos )
			timer:start( 1 )
		end
	end
})


code:
#The shortest rope will extend for this many meters. Longer ropes come in
#multiples of this length.
#Changing this value will not affect ropes that already exist in-world.
ropes_rope_length (Rope length) int 50 1 30000

#Rope ladders will extend this far at maximum.
#Changing this value will not affect rope ladders that already exist in-world.
#Setting this to 0 disables rope ladders.
ropes_rope_ladder_length (Rope ladder length) int 50 0 30000

#Sets the maximum length multiple wooden rope box permitted to be crafted.
#So for example if the rope length is set to 50 and this is set to 2,
#the longest possible wooden rope box a player can craft has 100 meters of rope.
#Allowed values run from 0 to 9. 0 disables wood rope boxes.
ropes_wood_rope_box_max_multiple (Maximum wood_rope box multiple) int 2 0 9

#Sets the maximum length multiple copper rope box permitted to be crafted.
#So for example if the rope length is set to 50 and this is set to 5,
#the longest possible copper rope box a player can craft has 250 meters of rope.
#Allowed values run from 0 to 9. 0 disables copper rope boxes.
ropes_copper_rope_box_max_multiple (Maximum copper rope box multiple) int 5 0 9

#Sets the maximum length multiple steel rope box permitted to be crafted.
#So for example if the rope length is set to 50 and this is set to 9,
#the longest possible steel rope box a player can craft has 450 meters of rope.
#Allowed values run from 0 to 9. 0 disables steel rope boxes.
ropes_steel_rope_box_max_multiple (Maximum steel rope box multiple) int 9 0 9

#If this is set to true, then the mod will generate definitions for the rope boxes
#that are otherwise not permitted by the settings above. These rope boxes
#will not be craftable and will not be available in the creative inventory,
#but they will continue to exist if they were placed "in world" and a player
#can deconstruct them to retrieve their rope components. This setting is
#intended for the situation where you have an established world and you want
#to reduce the number of rope boxes available to players without turning
#existing rope boxes into "unknown node"s.
ropes_create_all_definitions (Create all rope box definitions) bool false

#Extending ladders are capable of standing on their own, to a defined limit.
#A ladder can extend to its unsupported limit before needing another node
#behind it to provide a new point of support. Right-clicking on an existing
#ladder with a stack of ladders will add new ladder segments to its top.
ropes_extending_ladder_enabled (Enable extendable ladders) bool true

#If extending ladders are enabled, this setting will cause them to replace
#the default ladders entirely.
ropes_replace_default_ladders (Replace default ladders with extendable ladders) bool false

ropes_extending_wood_ladder_limit (Unsupported limit of wooden ladders) int 5
ropes_extending_steel_ladder_limit (Unsupported limit of steel ladders) int 15

#These nodes make it easier to build bridges by extending out away
#from the player as they're placed
ropes_bridges_enabled (Enable bridges) bool true


code:
# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs     diff=csharp

# Standard to msysgit
*.doc	 diff=astextplain
*.DOC	 diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot  diff=astextplain
*.DOT  diff=astextplain
*.pdf  diff=astextplain
*.PDF	 diff=astextplain
*.rtf	 diff=astextplain
*.RTF	 diff=astextplain


code:
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# =========================
# Operating System Files
# =========================

# OSX
# =========================

.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


code:
# scifi_nodes
Minetest mod that adds scifi themed nodes

**Adding Recipes for the unfinished scifi_nodes**

** Added support for stairsplus **

# Attributions

CC BY 3.0
* scifi_nodes_door_normal.ogg tlwmdbt https://freesound.org/people/tlwmdbt/sounds/165862/
* scifi_nodes_door_mechanic.ogg freedoom https://github.com/freedoom/freedoom


code:
default
technic?
xpanes?
moreblocks?
mesecons?
mesecons_microcontroller?
mesecons_button?
mesecons_torch?
mesecons_receiver?
dye?


code:
-- mydoors mod by don
-- DO WHAT YOU WANT TO PUBLIC LICENSE
-- or abbreviated DWYWPL

-- December 2nd 2015
-- License Copyright (C) 2015 Michael Tomaino (PlatinumArts@gmail.com)
-- www.sandboxgamemaker.com/DWYWPL/

-- DO WHAT YOU WANT TO PUBLIC LICENSE
-- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

-- 1. You are allowed to do whatever you want to with what content is using this license.
-- 2. This content is provided 'as-is', without any express or implied warranty. In no event
-- will the authors be held liable for any damages arising from the use of this content.

local doors = {
	-- Black door
	{"scifi_nodes:door2a","scifi_nodes:door2b","scifi_nodes:door2c","scifi_nodes:door2d","2","black", "doors:door_steel", "scifi_nodes_door_mechanic"},
	-- White door
	{"scifi_nodes:door3a","scifi_nodes:door3b","scifi_nodes:door3c","scifi_nodes:door3d","3","white", "doors:door_glass", "scifi_nodes_door_normal"},
	-- Green door
	{"scifi_nodes:door4a","scifi_nodes:door4b","scifi_nodes:door4c","scifi_nodes:door4d","4","green", "doors:door_wood", "scifi_nodes_door_mechanic"},
	-- DOOM door
	{"scifi_nodes:door1a","scifi_nodes:door1b","scifi_nodes:door1c","scifi_nodes:door1d","1","Doom", "doors:door_obsidian_glass", "scifi_nodes_door_mechanic"}
}

for i in ipairs (doors) do

-- TODO: make a map with entries: {a="", b="", desc="", etc}
local doora = doors[i][1]
local doorb = doors[i][2]
local doorc = doors[i][3]
local doord = doors[i][4]
local num = doors[i][5]
local des = doors[i][6]
local base_ingredient = doors[i][7]
local sound = doors[i][8]

minetest.register_craft({
    output = doora .. " 2",
    recipe = {
        {"default:steel_ingot", base_ingredient, "default:steel_ingot"},
        {"default:steel_ingot", base_ingredient, "default:steel_ingot"}
    }
})

function onplace(itemstack, placer, pointed_thing)
	local pos1 = pointed_thing.above
	local pos2 = {x=pos1.x, y=pos1.y, z=pos1.z}
	      pos2.y = pos2.y+1
	if

	not minetest.registered_nodes[minetest.get_node(pos1).name].buildable_to or
	not minetest.registered_nodes[minetest.get_node(pos2).name].buildable_to or
	not placer or
	not placer:is_player() or
	minetest.is_protected(pos1, placer:get_player_name()) or
	minetest.is_protected(pos2, placer:get_player_name()) then
		return
	end
			local pt = pointed_thing.above
			local pt2 = {x=pt.x, y=pt.y, z=pt.z}
			pt2.y = pt2.y+1
			local p2 = minetest.dir_to_facedir(placer:get_look_dir())
			local pt3 = {x=pt.x, y=pt.y, z=pt.z}
			local p4 = 0
			if p2 == 0 then
				pt3.x = pt3.x-1
				p4 = 2
			elseif p2 == 1 then
				pt3.z = pt3.z+1
				p4 = 3
			elseif p2 == 2 then
				pt3.x = pt3.x+1
				p4 = 0
			elseif p2 == 3 then
				pt3.z = pt3.z-1
				p4 = 1
			end
			if minetest.get_node(pt3).name == doora then
				minetest.set_node(pt, {name=doora, param2=p4})
				minetest.set_node(pt2, {name=doorb, param2=p4})
			else
				minetest.set_node(pt, {name=doora, param2=p2})
				minetest.set_node(pt2, {name=doorb, param2=p2})
			end
	itemstack:take_item(1)

	return itemstack;
end

function afterdestruct(pos, oldnode)
	   minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z},{name="air"})
end

function rightclick(pos, node, player, itemstack, pointed_thing)
	-- play sound
	minetest.sound_play(sound,{
		max_hear_distance = 16,
		pos = pos,
		gain = 1.0
	})

	local timer = minetest.get_node_timer(pos)
	local a = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-1})
	local b = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1})
	local c = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z})
	local d = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z})
	local e = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z-1})
	local f = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z-1})
	local g = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z+1})
	local h = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z+1})

		minetest.set_node(pos, {name=doorc, param2=node.param2})
		minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z}, {name=doord, param2=node.param2})

	     if a.name == doora then
		minetest.set_node({x=pos.x, y=pos.y, z=pos.z-1}, {name=doorc, param2=a.param2})
		minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z-1}, {name=doord, param2=a.param2})
		end
	     if b.name == doora then
		minetest.set_node({x=pos.x, y=pos.y, z=pos.z+1}, {name=doorc, param2=b.param2})
		minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z+1}, {name=doord, param2=b.param2})
		end
	     if c.name == doora then
		minetest.set_node({x=pos.x+1, y=pos.y, z=pos.z}, {name=doorc, param2=c.param2})
		minetest.set_node({x=pos.x+1,y=pos.y+1,z=pos.z}, {name=doord, param2=c.param2})
		end
	     if d.name == doora then
		minetest.set_node({x=pos.x-1, y=pos.y, z=pos.z}, {name=doorc, param2=d.param2})
		minetest.set_node({x=pos.x-1,y=pos.y+1,z=pos.z}, {name=doord, param2=d.param2})
		end
	     if e.name == doora then
		minetest.set_node({x=pos.x+1, y=pos.y, z=pos.z-1}, {name=doorc, param2=e.param2})
		minetest.set_node({x=pos.x+1, y=pos.y+1, z=pos.z-1}, {name=doord, param2=e.param2})
		end
	     if f.name == doora then
		minetest.set_node({x=pos.x-1, y=pos.y, z=pos.z-1}, {name=doorc, param2=f.param2})
		minetest.set_node({x=pos.x-1, y=pos.y+1, z=pos.z-1}, {name=doord, param2=f.param2})
		end
	     if g.name == doora then
		minetest.set_node({x=pos.x+1, y=pos.y, z=pos.z+1}, {name=doorc, param2=g.param2})
		minetest.set_node({x=pos.x+1, y=pos.y+1, z=pos.z+1}, {name=doord, param2=g.param2})
		end
	     if h.name == doora then
		minetest.set_node({x=pos.x-1, y=pos.y, z=pos.z+1}, {name=doorc, param2=h.param2})
		minetest.set_node({x=pos.x-1, y=pos.y+1, z=pos.z+1}, {name=doord, param2=h.param2})
		end

	   timer:start(3)

end

function afterplace(pos, placer, itemstack, pointed_thing)
	   minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z},{name=doord,param2=nodeu.param2})
end

function ontimer(pos, elapsed)
	-- play sound
	minetest.sound_play(sound,{
		max_hear_distance = 16,
		pos = pos,
		gain = 1.0
	})

	local node = minetest.get_node(pos)
	local a = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-1})
	local b = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1})
	local c = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z})
	local d = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z})
	local e = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z-1})
	local f = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z-1})
	local g = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z+1})
	local h = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z+1})

		minetest.set_node(pos, {name=doora, param2=node.param2})
		minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z}, {name=doorb, param2=node.param2})

	     if a.name == doorc then
		minetest.set_node({x=pos.x, y=pos.y, z=pos.z-1}, {name=doora, param2=a.param2})
		minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z-1}, {name=doorb, param2=a.param2})
		end
	     if b.name == doorc then
		minetest.set_node({x=pos.x, y=pos.y, z=pos.z+1}, {name=doora, param2=b.param2})
		minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z+1}, {name=doorb, param2=b.param2})
		end
	     if c.name == doorc then
		minetest.set_node({x=pos.x+1, y=pos.y, z=pos.z}, {name=doora, param2=c.param2})
		minetest.set_node({x=pos.x+1,y=pos.y+1,z=pos.z}, {name=doorb, param2=c.param2})
		end
	     if d.name == doorc then
		minetest.set_node({x=pos.x-1, y=pos.y, z=pos.z}, {name=doora, param2=d.param2})
		minetest.set_node({x=pos.x-1,y=pos.y+1,z=pos.z}, {name=doorb, param2=d.param2})
		end
	     if e.name == doorc then
		minetest.set_node({x=pos.x+1, y=pos.y, z=pos.z-1}, {name=doora, param2=e.param2})
		minetest.set_node({x=pos.x+1, y=pos.y+1, z=pos.z-1}, {name=doorb, param2=e.param2})
		end
	     if f.name == doorc then
		minetest.set_node({x=pos.x-1, y=pos.y, z=pos.z-1}, {name=doora, param2=f.param2})
		minetest.set_node({x=pos.x-1, y=pos.y+1, z=pos.z-1}, {name=doorb, param2=f.param2})
		end
	     if g.name == doorc then
		minetest.set_node({x=pos.x+1, y=pos.y, z=pos.z+1}, {name=doora, param2=g.param2})
		minetest.set_node({x=pos.x+1, y=pos.y+1, z=pos.z+1}, {name=doorb, param2=g.param2})
		end
	     if h.name == doorc then
		minetest.set_node({x=pos.x-1, y=pos.y, z=pos.z+1}, {name=doora, param2=h.param2})
		minetest.set_node({x=pos.x-1, y=pos.y+1, z=pos.z+1}, {name=doorb, param2=h.param2})
		end

end

minetest.register_node(doora, {
	description = des.." Sliding Door",
	inventory_image = "scifi_nodes_door"..num.."a_inv.png",
	wield_image = "scifi_nodes_door"..num.."a_inv.png",
	tiles = {
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_rbottom.png",
		"scifi_nodes_door"..num.."a_bottom.png"
	},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	groups = {cracky = 3},
	node_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.0625, 0.5, 0.5, 0.0625}
		}
	},
	selection_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.0625, 0.5, 1.5, 0.0625}
		}
	},

on_place = onplace,

after_destruct = afterdestruct,

on_rightclick = rightclick,
})
minetest.register_node(doorb, {
	tiles = {
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_rtop.png",
		"scifi_nodes_door"..num.."a_top.png"
	},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	groups = {cracky = 1},
	node_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.0625, 0.5, 0.5, 0.0625}
		}
	},
	selection_box = {
		type = "fixed",
		fixed = {
			{0, 0, 0, 0, 0, 0},
		}
	},
})
minetest.register_node(doorc, {
	tiles = {
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_rbottom0.png",
		"scifi_nodes_door"..num.."a_bottom0.png"
	},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	drop = doora,
	groups = {cracky = 1},
	node_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.0625, -0.25, 0.5, 0.0625},
		}
	},
	selection_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.0625, -0.25, 1.5, 0.0625},
		}
	},
after_place_node = afterplace,
after_destruct = afterdestruct,
on_timer = ontimer,
})
minetest.register_node(doord, {
	tiles = {
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_edge.png",
		"scifi_nodes_door"..num.."a_rtopo.png",
		"scifi_nodes_door"..num.."a_topo.png"
	},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	groups = {cracky = 1},
	node_box = {
		type = "fixed",
		fixed = {
			{-0.5, -0.5, -0.0625, -0.25, 0.5, 0.0625},
		}
	},
	selection_box = {
		type = "fixed",
		fixed = {
			{0, 0, 0, 0, 0, 0},
		}
	},
})
end


code:
--scifi_nodes by D00Med
dofile(minetest.get_modpath("scifi_nodes").."/doors.lua")
dofile(minetest.get_modpath("scifi_nodes").."/nodeboxes.lua")


code:
name = scifi_nodes
description = A mod which the vegan kitchen to Minetest.
depends = default,dye
optional_depends = xpanes,moreblocks,mesecons,mesecons_microcontroller,mesecons_button,mesecons_torch,mesecons_receiver


code:
-- GENERATED CODE
-- Node Box Editor, version 0.9.0

position1 = nil
position2 = nil

minetest.register_node("scifi_nodes:egg", {
	description = "Alien Egg",
	tiles = {
		"scifi_nodes_egg_top.png",
		"scifi_nodes_egg_top.png",
		"scifi_nodes_egg_side.png",
		"scifi_nodes_egg_side.png",
		"scifi_nodes_egg_side.png",
		"scifi_nodes_egg_side.png"
	},
	sunlight_propagates = false,
	drawtype = "nodebox",
	paramtype = "light",
	groups = {cracky=1, oddly_breakable_by_hand=1, dig_immediate=2, falling_node=1},
	light_source = 5,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.25, -0.5, -0.25, 0.25, -0.4375, 0.25}, -- NodeBox1
			{-0.375, -0.4375, -0.375, 0.375, -0.3125, 0.375}, -- NodeBox2
			{-0.4375, -0.3125, -0.375, 0.4375, 0.3125, 0.375}, -- NodeBox3
			{-0.375, 0.3125, -0.375, 0.375, 0.4375, 0.375}, -- NodeBox4
			{-0.3125, 0.4375, -0.3125, 0.3125, 0.5625, 0.3125}, -- NodeBox5
			{-0.25, 0.5625, -0.25, 0.25, 0.6875, 0.25}, -- NodeBox6
			{-0.1875, 0.6875, -0.1875, 0.1875, 0.75, 0.1875}, -- NodeBox7
			{-0.125, 0.75, -0.125, 0.125, 0.8125, 0.125}, -- NodeBox8
			{-0.375, -0.3125, -0.4375, 0.375, 0.3125, 0.4375}, -- NodeBox9
		}
	}
})

if minetest.get_modpath("scifi_mobs") then
minetest.register_abm({
	nodenames = {"scifi_nodes:egg"},
	interval = 30, chance = 10,
	action = function(pos, node, _, _)
		minetest.env:add_entity(pos, "scifi_mobs:xenomorph")
		minetest.env:remove_node(pos)
	end
})
end


code:
# Auto detect text files and perform LF normalization
* text=auto


code:
Sara's Simple Survival Game mod: signs
==========================

License of source code
----------------------
Copyright (C) 2018-2020 MultiCraft Development Team

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3.0 of the License, or
(at your option) any later version.

http://www.gnu.org/licenses/lgpl-3.0.html

License of textures
-------------------
Copyright (C) 2018-2020 MultiCraft Development Team

CC-BY-SA 4.0


code:
local vadd = vector.add
local floor, pi = math.floor, math.pi

local sign_positions = {
	[0] = {{x =  0,    y = 0.18, z = -0.07}, pi},
	[1] = {{x = -0.07, y = 0.18, z =  0},    pi * 0.5},
	[2] = {{x =  0,    y = 0.18, z =  0.07}, 0},
	[3] = {{x =  0.07, y = 0.18, z =  0},    pi * 1.5}
}

local wall_sign_positions = {
	[0] = {{x =  0.43, y = -0.005, z =  0},    pi * 0.5},
	[1] = {{x = -0.43, y = -0.005, z =  0},    pi * 1.5},
	[2] = {{x =  0,    y = -0.005, z =  0.43}, pi},
	[3] = {{x =  0,    y = -0.005, z = -0.43}, 0}
}

local function generate_sign_line_texture(str, row)
	local leftover = floor((20 - #str) * 16 / 2)
	local texture = ""
	for i = 1, 20 do
		local char = str:byte(i)
		if char and (char >= 32 and char <= 126) then
			texture = texture .. ":" .. (i - 1) * 16 + leftover .. ","
					.. row * 20 .. "=signs_" .. char .. ".png"
		end
	end

	return texture
end

local function find_any(str, pair, start)
	local ret = 0 -- 0 if not found (indices start at 1)
	for _, needle in pairs(pair) do
		local first = str:find(needle, start)
		if first then
			if ret == 0 or first < ret then
				ret = first
			end
		end
	end

	return ret
end

local disposable_chars = {["\n"] = true, ["\r"] = true, ["\t"] = true, [" "] = true}
local wrap_chars = {"\n", "\r", "\t", " ", "-", "/", ";", ":", ",", ".", "?", "!"}
local slugify = dofile(minetest.get_modpath("signs") .. "/slugify.lua")

local function generate_sign_texture(str)
	if not str or str == "" then
		return "blank.png"
	end
	local row = 0
	local texture = "[combine:" .. 16 * 20 .. "x100"
	local result = {}

	-- Transliterate text
	str = slugify(str)

	while #str > 0 do
		if row > 4 then
			break
		end
		local wrap_i = 0
		local keep_i = 0 -- The last character that was kept
		while wrap_i < #str do
			wrap_i = find_any(str, wrap_chars, wrap_i + 1)
			if wrap_i > 20 then
				if keep_i > 1 then
					wrap_i = keep_i
				else
					wrap_i = 20
				end
				break
			elseif wrap_i == 0 then
				if #str <= 20 then
					wrap_i = #str
				elseif keep_i > 0 then
					wrap_i = keep_i
				else
					wrap_i = #str
				end
				break
			elseif str:sub(wrap_i, wrap_i) == "\n" then
				break
			end
			if not disposable_chars[str:sub(wrap_i, wrap_i)] then
				keep_i = wrap_i
			elseif wrap_i > 1 and not disposable_chars[str:sub(wrap_i - 1, wrap_i - 1)] then
				keep_i = wrap_i - 1
			end
		end
		if wrap_i > 20 then
			wrap_i = 20
		end
		local start_remove = 0
		if disposable_chars[str:sub(1, 1)] then
			start_remove = 1
		end
		local end_remove = 0
		if disposable_chars[str:sub(wrap_i, wrap_i)] then
			end_remove = 1
		end
		local line_string = str:sub(1 + start_remove, wrap_i - end_remove)
		str = str:sub(wrap_i + 1)
		if line_string ~= "" then
			result[row] = line_string
		end
		row = row + 1
	end

	local empty = 0
	if row == 1 then
		empty = 2
	elseif row < 4 then
		empty = 1
	end

	for r, s in pairs(result) do
		texture = texture .. generate_sign_line_texture(s, r + empty)
	end

	return texture
end

minetest.register_entity("signs:sign_text", {
	visual = "upright_sprite",
	visual_size = {x = 0.7, y = 0.6},
	collisionbox = {0},
	pointable = false,
	on_activate = function(self)
		local ent = self.object
		local pos = ent:get_pos()

		-- remove entity for missing sign
		local node_name = minetest.get_node(pos).name
		if not node_name == "signs:sign" and not node_name == "signs:wall_sign" then
			ent:remove()
			return
		end

		local meta = minetest.get_meta(pos)
		local meta_texture = meta:get_string("sign_texture")

		local texture
		if meta_texture and meta_texture ~= "" then
			texture = meta_texture
		else
			local meta_text = meta:get_string("sign_text")
			if meta_text and meta_text ~= "" then
				texture = generate_sign_texture(meta_text)
			else
				texture = "blank.png"
			end
			meta:set_string("sign_texture", texture)
		end

		ent:set_properties({
			textures = {texture, "blank.png"}
		})
	end
})

local function check_text(pos)
	local meta = minetest.get_meta(pos)
	local text = meta:get_string("sign_text")
	local objects = minetest.get_objects_inside_radius(pos, 0.5)

	if text and text ~= "" then
		local count = 0
		for _, obj in pairs(objects) do
			local ent = obj:get_luaentity()
			if ent and ent.name == "signs:sign_text" then
				count = count + 1
				if count > 1 then
					obj:remove()
				end
			end
		end
		if count == 0 then
			local node = minetest.get_node(pos)
			local p2 = node.param2 or -1
			local sign_pos = sign_positions
			if node.name == "signs:wall_sign" then
				p2 = p2 - 2
				sign_pos = wall_sign_positions
			end
			if p2 > 3 or p2 < 0 then return end
			local obj = minetest.add_entity(
				vadd(pos, sign_pos[p2][1]), "signs:sign_text")
			obj:set_yaw(sign_pos[p2][2])
		end
	else
		for _, obj in pairs(objects) do
			local ent = obj:get_luaentity()
			if ent and ent.name == "signs:sign_text" then
				obj:remove()
			end
		end
	end
end

--minetest.register_lbm({
--	label = "Check for sign text",
--	name = "signs:sign_text",
--	nodenames = {"signs:sign", "signs:wall_sign"},
--	run_at_every_load = true,
--	action = check_text
--})

local function construct(pos)
	local meta = minetest.get_meta(pos)
	meta:set_string("formspec", "size[5,3]" ..
			"textarea[1.15,0.3;3.3,2;Dtext;" .. "Enter your text:" .. ";${sign_text}]" ..
			"button_exit[0.85,2;3.3,1;;" .. "Save" .. "]")
end

local function destruct(pos)
	for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
		local ent = obj:get_luaentity()
		if ent and ent.name == "signs:sign_text" then
			obj:remove()
		end
	end
end

local function receive_fields(pos, _, fields, sender, wall)
	local text = fields.Dtext
	if not text then return end
	if minetest.is_protected(pos, sender:get_player_name()) then
		return
	end
	local p2 = minetest.get_node(pos).param2
	local sign_pos = sign_positions
	if wall then
		p2 = p2 - 2
		sign_pos = wall_sign_positions
	end
	if not p2 or p2 > 3 or p2 < 0 then return end
	local sign
	for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
		local ent = obj:get_luaentity()
		if ent and ent.name == "signs:sign_text" then
			sign = obj
			break
		end
	end
	if not sign then
		sign = minetest.add_entity(
			vadd(pos, sign_pos[p2][1]), "signs:sign_text")
	else
		sign:set_pos(vadd(pos, sign_pos[p2][1]))
	end
	local texture = generate_sign_texture(text)
	sign:set_properties({
		textures = {texture, "blank.png"}
	})
	sign:set_yaw(sign_pos[p2][2])
	local meta = minetest.get_meta(pos)
	meta:set_string("sign_text", text)
	meta:set_string("sign_texture", texture)
end

minetest.register_node("signs:sign", {
	description = "Sign",
	tiles = {"signs_wood.png"},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	node_placement_prediction = "",
	sunlight_propagates = true,
	node_box = {
		type = "fixed",
		fixed = {
			{-0.375, -0.125, -0.063, 0.375,  0.5,   0.063},
			{-0.063, -0.5,   -0.063, 0.063, -0.125, 0.063}
		}
	},
	groups = {oddly_breakable_by_hand = 1, choppy = 3, attached_node = 1},

	on_place = function(itemstack, placer, pointed_thing)
		if pointed_thing.type == "node" then
			local under = pointed_thing.under
			local node = minetest.get_node(under)
			local node_def = minetest.registered_nodes[node.name]
			if node_def and node_def.on_rightclick and
					not (placer and placer:is_player() and
					placer:get_player_control().sneak) then
				return node_def.on_rightclick(under, node, placer, itemstack,
					pointed_thing) or itemstack
			end

			local undery = pointed_thing.under.y
			local posy = pointed_thing.above.y

			local _, result
			if undery < posy then -- Floor sign
				itemstack, result = minetest.item_place(itemstack,
						placer, pointed_thing)
			elseif undery == posy then -- Wall sign
				_, result = minetest.item_place(ItemStack("signs:wall_sign"),
						placer, pointed_thing)
				if result and not (creative and creative.is_enabled_for and
						creative.is_enabled_for(placer)) then
					itemstack:take_item()
				end
			end
			if result then
				minetest.sound_play({name = "default_place_node_hard"},
						{pos = pointed_thing.above})
			end
		end

		return itemstack
	end,

	on_construct = construct,
	on_destruct = destruct,
	on_punch = check_text,
	on_receive_fields = receive_fields
})

minetest.register_node("signs:wall_sign", {
	tiles = {"signs_wood.png"},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "wallmounted",
	node_box = {
		type = "wallmounted",
		wall_side = {-0.5, -0.313, -0.438, -0.438, 0.313, 0.438}
	},
	drop = "signs:sign",
	walkable = false,
	groups = {oddly_breakable_by_hand = 1, choppy = 3,
		not_in_creative_inventory = 1, attached_node = 1},

	on_construct = construct,
	on_destruct = destruct,
	on_punch = check_text,

	on_receive_fields = function(pos, _, fields, sender)
		receive_fields(pos, _, fields, sender, true)
	end
})

minetest.register_craft({
	output = "signs:sign 3",
	recipe = {
		{"group:wood", "group:wood", "group:wood"},
		{"group:wood", "group:wood", "group:wood"},
		{"", "group:stick", ""}
	}
})

minetest.register_craft({
	type = "fuel",
	recipe = "signs:sign",
	burntime = 10
})

-- Create Alis for mods that use default:sign_
minetest.register_alias("default:sign_wall_wood", "signs:wall_sign")


code:
name = signs
depends = default
description = Lightweight wooden signs with text display and automatic formatting.


code:
slats = {}

function slats.register_slat(subname, recipeitem, groups, image, description, sounds)
	groups.slab = 1
	minetest.register_node(":slats:slat_" .. subname, {
		description = description,
		drawtype = "nodebox",
		tiles = {image},
		inventory_image = image,
		wield_image = image,
		paramtype = "light",
		paramtype2 = "wallmounted",
		is_ground_content = false,
		sunlight_propagates = true,
		groups = groups,
		sounds = sounds,
		node_box = {
			type = "wallmounted",
				wall_top    = {-0.5, 0.49, -0.5, 0.5, 0.49, 0.5},
				wall_bottom = {-0.5, -0.49, -0.5, 0.5, -0.49, 0.5},
				wall_side   = {-0.49, -0.5, -0.5, -0.49, 0.5, 0.5},
		},
	})

	if recipeitem then
		minetest.register_craft({
			type = "shapeless",
			output = 'slats:slat_' .. subname .. ' 12',
			recipe = {recipeitem, "default:paper"},
		})

		-- Fuel
		local baseburntime = minetest.get_craft_result({
			method = "fuel",
			width = 1,
			items = {recipeitem}
		}).time
		if baseburntime > 0 then
			minetest.register_craft({
				type = "fuel",
				recipe = 'slats:slat_' .. subname,
				burntime = math.floor(baseburntime * 0.5),
			})
		end
	end
end

slats.register_slat(
	"stone_block",
	"default:stone_block",
	{cracky = 2},
	"default_stone_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Stone Block Slat",
	default.node_sound_stone_defaults()
)

slats.register_slat(
	"desert_stone_block",
	"default:desert_stone_block",
	{cracky = 2},
	"default_desert_stone_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Desert Stone Block Slat",
	default.node_sound_stone_defaults()
)

slats.register_slat(
	"sandstone_block",
	"default:sandstone_block",
	{cracky = 2},
	"default_sandstone_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Sandstone Block Slat",
	default.node_sound_stone_defaults()
)

slats.register_slat(
	"desert_sandstone_block",
	"default:desert_sandstone_block",
	{cracky = 2},
	"default_desert_sandstone_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Desert Sandstone Block Slat",
	default.node_sound_stone_defaults()
)

slats.register_slat(
	"silver_sandstone_block",
	"default:silver_sandstone_block",
	{cracky = 2},
	"default_silver_sandstone_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Silver Sandstone Block Slat",
	default.node_sound_stone_defaults()
)

slats.register_slat(
	"obsidian_block",
	"default:obsidian_block",
	{cracky = 1, level = 2},
	"default_obsidian_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Obsidian Block Slat",
	default.node_sound_stone_defaults()
)

slats.register_slat(
	"steelblock",
	"default:steelblock",
	{cracky = 1, level = 2},
	"default_steel_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Steel Block Slat",
	default.node_sound_metal_defaults()
)

slats.register_slat(
	"copperblock",
	"default:copperblock",
	{cracky = 1, level = 2},
	"default_copper_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Copper Block Slat",
	default.node_sound_metal_defaults()
)

slats.register_slat(
	"bronzeblock",
	"default:bronzeblock",
	{cracky = 1, level = 2},
	"default_bronze_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Bronze Block Slat",
	default.node_sound_metal_defaults()
)

slats.register_slat(
	"goldblock",
	"default:goldblock",
	{cracky = 1},
	"default_gold_block.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Gold Block Slat",
	default.node_sound_metal_defaults()
)

slats.register_slat(
	"wood",
	"default:wood",
	{choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
	"default_wood.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Wooden Slat",
	default.node_sound_wood_defaults()
)

slats.register_slat(
	"junglewood",
	"default:junglewood",
	{choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
	"default_junglewood.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Jungle Wood Slat",
	default.node_sound_wood_defaults()
)

slats.register_slat(
	"pine_wood",
	"default:pine_wood",
	{choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
	"default_pine_wood.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Pine Wood Slat",
	default.node_sound_wood_defaults()
)

slats.register_slat(
	"acacia_wood",
	"default:acacia_wood",
	{choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
	"default_acacia_wood.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Acacia Wood Slat",
	default.node_sound_wood_defaults()
)

slats.register_slat(
	"aspen_wood",
	"default:aspen_wood",
	{choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
	"default_aspen_wood.png^slats_slat_overlay.png^[makealpha:255,126,126",
	"Aspen Wood Slat",
	default.node_sound_wood_defaults()
)


code:
name = slats
depends = default


code:
This mod provides a single new block type: a sounding line on a spool. Build the sounding line in-world and right click on it to get a measure of how far down the surface of the water below it is (if any), and how far down below the first solid obstruction is.

The sounding line can be crafted using cotton (from the farming mod) or ropes and vines (from the ropes and vines mods)


code:
-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

local data = {}

local node_sound
if minetest.get_modpath("default") then
	node_sound = default.node_sound_wood_defaults()
end

local particles = minetest.settings:get_bool("enable_particles")
if particles == "true" or particles == true or particles == nil then
	particles = true -- default true
else
	particles = false
end

minetest.register_node("sounding_line:sounding_line", {
	description = S("Sounding Line"),
	_doc_items_longdesc = S("A spool of marked line with a weight on the end used for measuring depths."),
    _doc_items_usagehelp = S("Build this item over the location whose depths you wish to plumb. Right click on it to take a reading. The sounding line will give a reading indicating how far down the sounding line encountered water (if any) and how far down the first solid obstruction is.\n\nIf lava is encountered this will be indicated by a burnt end on the line. Sounding lines can't measure the depth of lava, only how far it is to the lava's surface.\n\nIf the sounding line reports encountering an \"unknown void\" it has reached a region that has not yet been generated by map generation."),
	groups = {cracky = 3, oddly_breakable_by_hand=3},
	drop = "sounding_line:sounding_line",
	tiles = {"sounding_line_top.png","sounding_line_bottom.png",
		"sounding_line_side.png","sounding_line_side.png^[transformFX",
		"sounding_line_front.png","sounding_line_front.png^[transformFX"},
	sounds = node_sound,
	climbable = true,
	walkable = false,
	paramtype = "light",
	paramtype2 = "facedir",
	is_ground_content = false,

	drawtype = "nodebox",
	paramtype = "light",
	node_box = {
		type = "fixed",
		fixed = {
			{-0.375, 0.125, -0.0625, 0.375, 0.25, 0.0625}, -- crossbar
			{-0.5, 0.125, -0.5, -0.375, 0.25, 0.5}, -- leg
			{0.375, 0.125, -0.5, 0.5, 0.25, 0.5}, -- leg
			{0.1875, -0.125, -0.3125, 0.3125, 0.5, 0.3125}, -- spool
			{-0.3125, -0.125, -0.3125, -0.1875, 0.5, 0.3125}, -- spool
			{-0.1875, -0.0625, -0.25, 0.1875, 0.4375, 0.25}, -- line_roll
			{-0.0625, -0.25, -0.25, 0, -0.0625, -0.1875}, -- hanging_line
			{-0.125, -0.5, -0.3125, 0.0625, -0.25, -0.125}, -- weight
		}
	},

	on_rightclick = function(pos, node, player, itemstack, pointed_thing)
		local top = pos.y-1
		local bottom = pos.y-15
		local voxel_manip = minetest.get_voxel_manip()

		local end_depth, water_depth
		local encountered_lava, encountered_ignore

		while not end_depth do
			local emin, emax = voxel_manip:read_from_map({x=pos.x, y=bottom, z=pos.z}, {x=pos.x, y=top, z=pos.z})
			voxel_manip:get_data(data)
			local voxel_area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
			bottom = emin.y
			for y= top, bottom, -1 do
				local index = voxel_area:index(pos.x, y, pos.z)
				local name = minetest.get_name_from_content_id(data[index])
				if name == "ignore" then
					encountered_ignore = true
					end_depth = pos.y - y
				end
				if not water_depth and minetest.get_item_group(name, "water") > 0 then
					water_depth = pos.y - y
				end
				if not encountered_lava and minetest.get_item_group(name, "lava") > 0 then
					end_depth = y - pos.y
					encountered_lava = true
				end
				local def = minetest.registered_nodes[name]
				if def.walkable then
					end_depth = pos.y - y
				end

				if end_depth then
					break
				end
			end
			top = bottom - 1
			bottom = bottom - 15
		end

		local status = S("Most recent reading:")
		if water_depth then
			status = status .. "\n" .. string.format(S("Water %dm down"), water_depth)
		end
		if encountered_lava then
			status = status .. "\n" .. string.format(S("Line burned %dm down"), end_depth)
		elseif encountered_ignore then
			status = status .. "\n" .. string.format(S("Unknown void %dm down"), end_depth)
		else
			status = status .. "\n" .. string.format(S("Obstruction %dm down"), end_depth)
		end

		local meta = minetest.get_meta(pos)
		meta:set_string("infotext", status)

		if particles then
			minetest.add_particlespawner({
				amount = 50,
				time = 1,
				minpos = pos,
				maxpos = pos,
				minvel = {x=0, y=-10, z=0},
				maxvel = {x=0, y=-10, z=0},
				minacc = {x=0, y=0, z=0},
				maxacc = {x=0, y=0, z=0},
				minexptime = 1,
				maxexptime = 1,
				minsize = 8,
				maxsize = 8,
				collisiondetection = true,
				vertical = true,
				texture = "sounding_line_particle.png",
			})
		end

		minetest.sound_play("sounding_line_whooshing", {pos=pos, gain=0.5})
	end,
})

if minetest.get_modpath("farming") then
	local old_def = minetest.registered_craftitems["farming:cotton"]
	if old_def then
		old_def.groups["thread"] = 1
		minetest.override_item("farming:cotton", {
			groups = old_def.groups
		})
	end
end

if minetest.get_modpath("default") then
	minetest.register_craft({
		output = "sounding_line:sounding_line",
		recipe =  {
			{'group:stick','group:stick','group:stick'},
			{'group:thread','group:thread','group:thread'},
			{'','default:steel_ingot',''}
		}
	})

	minetest.register_craft({
		output = "sounding_line:sounding_line",
		recipe =  {
			{'group:stick','group:stick','group:stick'},
			{'','group:vines',''},
			{'','default:steel_ingot',''}
		}
	})
end

if minetest.get_modpath("loot") then
	loot.register_loot({
		weights = { generic = 50 },
		payload = {
			stack = ItemStack("sounding_line:sounding_line"),
			min_size = 1,
			max_size = 4,
		},
	})
end


code:
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.

-- Get the latest version of this file at:
--   https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua

local function format(str, ...)
	local args = { ... }
	local function repl(escape, open, num, close)
		if escape == "" then
			local replacement = tostring(args[tonumber(num)])
			if open == "" then
				replacement = replacement..close
			end
			return replacement
		else
			return "@"..open..num..close
		end
	end
	return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end

local gettext, ngettext
if minetest.get_modpath("intllib") then
	if intllib.make_gettext_pair then
		-- New method using gettext.
		gettext, ngettext = intllib.make_gettext_pair()
	else
		-- Old method using text files.
		gettext = intllib.Getter()
	end
end

-- Fill in missing functions.

gettext = gettext or function(msgid, ...)
	return format(msgid, ...)
end

ngettext = ngettext or function(msgid, msgid_plural, n, ...)
	return format(n==1 and msgid or msgid_plural, ...)
end

return gettext, ngettext


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-05 12:32-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: init.lua:13
msgid "Sounding Line"
msgstr ""

#: init.lua:14
msgid ""
"A spool of marked line with a weight on the end used for measuring depths."
msgstr ""

#: init.lua:15
msgid ""
"Build this item over the location whose depths you wish to plumb. Right "
"click on it to take a reading. The sounding line will give a reading "
"indicating how far down the sounding line encountered water (if any) and how "
"far down the first solid obstruction is.\n"
"\n"
"If lava is encountered this will be indicated by a burnt end on the line. "
"Sounding lines can't measure the depth of lava, only how far it is to the "
"lava's surface.\n"
"\n"
"If the sounding line reports encountering an \"unknown void\" it has reached "
"a region that has not yet been generated by map generation."
msgstr ""

#: init.lua:84
msgid "Most recent reading:"
msgstr ""

#: init.lua:86
#, c-format
msgid "Water %dm down"
msgstr ""

#: init.lua:89
#, c-format
msgid "Line burned %dm down"
msgstr ""

#: init.lua:91
#, c-format
msgid "Unknown void %dm down"
msgstr ""

#: init.lua:93
#, c-format
msgid "Obstruction %dm down"
msgstr ""


code:
name = sounding_line
description = A tool for determining the depth of water or the depth of a hole.
depends =
optional_depends = default, doc, intllib, farming, vines, loot
author = FaceDeer
title = Sounding Line


code:
minetest.register_craft({
	output = "spacesuit:helmet",
	recipe = {
		{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
		{"default:steel_ingot", "default:glass", "default:steel_ingot"},
		{"wool:white", "default:steelblock", "wool:white"},
	},
})

minetest.register_craft({
	output = "spacesuit:chestplate",
	recipe = {
		{"default:steel_ingot", "default:mese", "default:steel_ingot"},
		{"default:steel_ingot", "wool:white", "default:steel_ingot"},
		{"default:steel_ingot", "wool:white", "default:steel_ingot"}
	},
})

minetest.register_craft({
	output = "spacesuit:pants",
	recipe = {
		{"default:steel_ingot", "wool:white", "default:steel_ingot"},
		{"default:steel_ingot", "wool:white", "default:steel_ingot"},
		{"wool:white", "wool:white", "wool:white"}
	},
})

minetest.register_craft({
	output = "spacesuit:boots",
	recipe = {
		{"default:steel_ingot", "wool:white", "default:steel_ingot"},
		{"default:steel_ingot", "wool:white", "default:steel_ingot"},
		{"default:steel_ingot", "default:steelblock", "default:steel_ingot"},
	},
})


code:
local timer = 0
minetest.register_globalstep(function(dtime)
	timer = timer + dtime;
	if timer >= 1 then
		local t0 = minetest.get_us_time()

		for _,player in ipairs(minetest.get_connected_players()) do
			local name = player:get_player_name()

			local name, armor_inv = armor.get_valid_player(armor, player, "[spacesuit]")

			local has_helmet = armor_inv:contains_item("armor", "spacesuit:helmet")
			local has_chestplate = armor_inv:contains_item("armor", "spacesuit:chestplate")
			local has_pants = armor_inv:contains_item("armor", "spacesuit:pants")
			local has_boots = armor_inv:contains_item("armor", "spacesuit:boots")

			local has_full_suit = has_helmet and has_chestplate and has_pants and has_boots

			local armor_list = armor_inv:get_list("armor")

			-- does the player wear a suit?
			spacesuit.set_player_wearing(player, has_full_suit, has_helmet, armor_list)

			if has_full_suit and player:get_breath() < 10 then

				for i, stack in pairs(armor_inv:get_list("armor")) do
					if not stack:is_empty() then
						local name = stack:get_name()
						if name:sub(1, 10) == "spacesuit:" then
  						local use = minetest.get_item_group(name, "armor_use") * timer or 0
							armor:damage(player, i, stack, use)
						end
					end
				end

				player:set_breath(10)
			end
		end
		timer = 0

		local t1 = minetest.get_us_time()
		local diff = t1 - t0
		if diff > 10000 then
			minetest.log("warning", "[spacesuit] update took " .. diff .. " us")
		end
	end
end)


code:
local HUD_POSITION = {x = 0.1, y = 0.2}
local O2_BAR_OFFSET = {x = 0, y = 0}
local SUITE_INCOMPLETE_OFFSET = {x = 0, y = 20}
local HUD_ALIGNMENT = {x = 1, y = 0}

local hud = {} -- playername -> data

local setup_hud = function(player)
	local playername = player:get_player_name()
	local hud_data = {}
	hud[playername] = hud_data

	hud_data.overlay = player:hud_add({
	    hud_elem_type = "image",
	    position = {x = 0.5, y = 0.5},
	    scale = {
	      x = -100,
	      y = -100
	    },
	    text = "spacesuit_overlay.png"
	})

	hud_data.o2_bg = player:hud_add({
		hud_elem_type = "image",
		position = HUD_POSITION,
		offset = O2_BAR_OFFSET,
		text = "spacesuit_o2_levels_bg.png",
		alignment = HUD_ALIGNMENT,
		scale = {x = -80, y = 1}
	})

	hud_data.o2_fg = player:hud_add({
		hud_elem_type = "image",
		position = HUD_POSITION,
		offset = O2_BAR_OFFSET,
		text = "spacesuit_o2_levels_fg_green.png",
		alignment = HUD_ALIGNMENT,
		scale = {x = 0, y = 1}
	})

	hud_data.o2_label = player:hud_add({
		hud_elem_type = "text",
		position = HUD_POSITION,
		offset = {x = O2_BAR_OFFSET.x - 80,   y = O2_BAR_OFFSET.y},
		text = "O2-Level:",
		alignment = HUD_ALIGNMENT,
		scale = {x = 100, y = 100},
		number = 0x00FF00
	})

	hud_data.o2_level = player:hud_add({
		hud_elem_type = "text",
		position = {x = 1, y = HUD_POSITION.y },
		offset = {x = O2_BAR_OFFSET.x - 70,   y = O2_BAR_OFFSET.y},
		text = "",
		alignment = HUD_ALIGNMENT,
		scale = {x = 100, y = 100},
		number = 0x00FF00
	})

	hud_data.suit_incomplete = player:hud_add({
		hud_elem_type = "text",
		position = HUD_POSITION,
		offset = SUITE_INCOMPLETE_OFFSET,
		text = "",
		alignment = HUD_ALIGNMENT,
		scale = {x = 100, y = 100},
		number = 0xFF0000
	})

end

local remove_hud = function(player)
	local playername = player:get_player_name()
	local hud_data = hud[playername]

	player:hud_remove(hud_data.overlay)
	player:hud_remove(hud_data.o2_bg)
	player:hud_remove(hud_data.o2_fg)
	player:hud_remove(hud_data.o2_label)
	player:hud_remove(hud_data.o2_level)
	player:hud_remove(hud_data.suit_incomplete)

	hud[playername] = nil
end

local get_color = function(r,g,b)
	return b + (g * 256) + (r * 256 * 256)
end

local update_hud = function(player, has_full_suit, armor_list)
	local playername = player:get_player_name()
	local hud_data = hud[playername]

	if not hud_data then
		return
	end

	if has_full_suit then
		player:hud_change(hud_data.suit_incomplete, "text", "")
	else
		player:hud_change(hud_data.suit_incomplete, "text", "Spacesuit incomplete!")
	end

	local max_wear = 0
	for _,item in pairs(armor_list) do
		-- wear:0 == full, wear:65535 == empty
		if item:get_name() == "spacesuit:helmet" then
			max_wear = math.max(max_wear, item:get_wear())
		elseif item:get_name() == "spacesuit:chestplate" then
			max_wear = math.max(max_wear, item:get_wear())
		elseif item:get_name() == "spacesuit:pants" then
			max_wear = math.max(max_wear, item:get_wear())
		elseif item:get_name() == "spacesuit:boots" then
			max_wear = math.max(max_wear, item:get_wear())
		end
	end

	local factor_full = 1 - (max_wear / 65535)

	player:hud_change(hud_data.o2_level, "text", math.floor(factor_full * 100) .. "%")
	player:hud_change(hud_data.o2_fg, "scale", { x=math.floor(factor_full * -80), y=1 })

	local color

	if factor_full > 0.3 then
		-- green
		color = get_color(0,255,0)
		player:hud_change(hud_data.o2_fg, "text", "spacesuit_o2_levels_fg_green.png")

	elseif factor_full > 0.1 then
		-- yellow
		color = get_color(255,255,0)
		player:hud_change(hud_data.o2_fg, "text", "spacesuit_o2_levels_fg_yellow.png")

	else
		-- red
		color = get_color(255,0,0)
		player:hud_change(hud_data.o2_fg, "text", "spacesuit_o2_levels_fg_red.png")

	end

	player:hud_change(hud_data.o2_label, "number", color)
	player:hud_change(hud_data.o2_level, "number", color)

end

minetest.register_on_leaveplayer(function(player)
	-- remove stale hud data
	local playername = player:get_player_name()
	hud[playername] = nil
end)

spacesuit.set_player_wearing = function(player, has_full_suit, has_helmet, armor_list)
	local playername = player:get_player_name()
	local hud_data = hud[playername]

	if hud_data and has_helmet then
		-- player wears it
		update_hud(player, has_full_suit, armor_list)

	elseif not hud_data and not has_helmet then
		-- player does not wear it

	elseif hud_data and not has_helmet then
		-- player stopped wearing
		remove_hud(player)

	elseif not hud_data and has_helmet then
		-- player started wearing
		setup_hud(player)
		minetest.after(0.1, function()
			update_hud(player, has_full_suit, armor_list)
		end)

	end
end


code:
spacesuit = {
	armor_use = tonumber(minetest.settings:get("spacesuit.armor_use")) or 70,
}

local MP = minetest.get_modpath("spacesuit")

dofile(MP.."/suit.lua")
dofile(MP.."/crafts.lua")
dofile(MP.."/hud.lua")
dofile(MP.."/drowning.lua")
dofile(MP.."/repair.lua")

print("[OK] Spacesuit")


code:
name = spacesuit
description = Adds a space suit to survive in vacuum.
author = Buckaroo Banzay
depends = default, 3d_armor
optional_depends = vacuum


code:
# Intro

Spacesuit for minetest

# Dependencies
* 3d_armor
* vacuum?

# Features
* Breathe in vacuum or water

# Attributions
* Spacesuit textures: Anonymous_moose (https://forum.minetest.net/viewtopic.php?p=185473#p185473)
* textures/spacesuit_overlay.png (https://github.com/bas080/minetest_vignette)


code:
local has_vacuum = minetest.get_modpath("vacuum")

if has_vacuum then

	function repair_recipe(partname)
		minetest.register_craft({
			type = "shapeless",
			output = partname,
			recipe = {
				"vacuum:air_bottle",
				partname
			},
			replacements = {
				{"vacuum:air_bottle", "vessels:steel_bottle"}
			}
		})
	end

	repair_recipe("spacesuit:helmet")
	repair_recipe("spacesuit:chestplate")
	repair_recipe("spacesuit:pants")
	repair_recipe("spacesuit:boots")

end


code:
armor:register_armor("spacesuit:helmet", {
	description = "Spacesuit Helmet",
	inventory_image = "spacesuit_inv_helmet.png",
	groups = {armor_head=5, armor_heal=1, armor_use=spacesuit.armor_use, not_repaired_by_anvil=1},
	wear = 0,
	wear_represents = "spacesuit_wear",
})

minetest.register_tool("spacesuit:chestplate", {
	description = "Spacesuit Chestplate",
	inventory_image = "spacesuit_inv_chestplate.png",
	groups = {armor_torso=8, armor_heal=1, armor_use=spacesuit.armor_use, not_repaired_by_anvil=1},
	wear = 0,
	wear_represents = "spacesuit_wear",
})

minetest.register_tool("spacesuit:pants", {
	description = "Spacesuit Pants",
	inventory_image = "spacesuit_inv_pants.png",
	groups = {armor_legs=7, armor_heal=1, armor_use=spacesuit.armor_use, not_repaired_by_anvil=1},
	wear = 0,
	wear_represents = "spacesuit_wear",
})

minetest.register_tool("spacesuit:boots", {
	description = "Spacesuit Boots",
	inventory_image = "spacesuit_inv_boots.png",
	groups = {armor_feet=4, armor_heal=1, armor_use=spacesuit.armor_use, not_repaired_by_anvil=1},
	wear = 0,
	wear_represents = "spacesuit_wear",
})


code:
name = stm_nodes
description = Some steam-punk nodes. Trimmed by MeseCraft, will be gone soon.
depends = default, tnt
optional_depends =
author = D00Med
title = Steampunk Nodes


code:
# Auto detect text files and perform LF normalization
* text=auto


code:
# Compiled Lua sources
luac.out

# luarocks build files
*.src.rock
*.zip
*.tar.gz

# Object files
*.o
*.os
*.ko
*.obj
*.elf

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex