mirror of
				https://github.com/luanti-org/minetest_game.git
				synced 2025-10-31 07:35:22 +01:00 
			
		
		
		
	Compare commits
	
		
			46 Commits
		
	
	
		
			5.0.0
			...
			stable-0.4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d6a66860af | ||
|  | 6d850f23a5 | ||
|  | 2c1af0861f | ||
|  | d2ae721235 | ||
|  | 01db55cee5 | ||
|  | 4ba2b5179e | ||
|  | a5092c0df6 | ||
|  | 575c098bae | ||
|  | cddd59b578 | ||
|  | 7a4b1e0ce1 | ||
|  | 0216fa08ec | ||
|  | ca3e807d35 | ||
|  | ca38bb2390 | ||
|  | 7d07c52d09 | ||
|  | 532013a032 | ||
|  | a52622669f | ||
|  | ce5e668681 | ||
|  | 6530fa914b | ||
|  | 86eb0e1617 | ||
|  | 93fb9b36ce | ||
|  | 09e3505ea1 | ||
|  | cecbfc1676 | ||
|  | fba6f6a4cf | ||
|  | 6053456af1 | ||
|  | cc2f75b2f9 | ||
|  | b6ef71c92e | ||
|  | 876da2fbc6 | ||
|  | ea45ca57a5 | ||
|  | 6fa3ebfa75 | ||
|  | efe6fb6dfb | ||
|  | 1aeb2baa91 | ||
|  | e4d6425846 | ||
|  | 81f885795d | ||
|  | f3e29bc2cc | ||
|  | 3a72f7b84b | ||
|  | 20bd4560f8 | ||
|  | 8991b9fe54 | ||
|  | aea6c5dd1d | ||
|  | da41caca66 | ||
|  | 103af98864 | ||
|  | 26606b0520 | ||
|  | 706844e8bf | ||
|  | a56274c230 | ||
|  | 3512226867 | ||
|  | d5b9fee6fe | ||
|  | 437860feff | 
| @@ -155,7 +155,8 @@ The doors mod allows modders to register custom doors and trapdoors. | |||||||
| ### Fence gate definition | ### Fence gate definition | ||||||
|  |  | ||||||
| 	description = "Wooden Fence Gate", | 	description = "Wooden Fence Gate", | ||||||
| 	texture = "default_wood.png", | 	texture = "default_wood.png", -- `backface_culling` will automatically be | ||||||
|  | 	                              -- set to `true` if not specified. | ||||||
| 	material = "default:wood", | 	material = "default:wood", | ||||||
| 	groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, | 	groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, | ||||||
| 	sounds = default.node_sound_wood_defaults(), -- optional | 	sounds = default.node_sound_wood_defaults(), -- optional | ||||||
| @@ -303,12 +304,13 @@ TNT API | |||||||
|   * `bottom` Bottom tile. By default the name of the tnt with a suffix of `_bottom.png`. |   * `bottom` Bottom tile. By default the name of the tnt with a suffix of `_bottom.png`. | ||||||
|   * `burning` Top tile when lit. By default the name of the tnt with a suffix of `_top_burning_animated.png". |   * `burning` Top tile when lit. By default the name of the tnt with a suffix of `_top_burning_animated.png". | ||||||
|  |  | ||||||
| `tnt.boom(position, definition)` | `tnt.boom(position[, definition])` | ||||||
|  |  | ||||||
| ^ Create an explosion. | ^ Create an explosion. | ||||||
|  |  | ||||||
| * `position` The center of explosion. | * `position` The center of explosion. | ||||||
| * `definition` The TNT definion as passed to `tnt.register` | * `definition` The TNT definion as passed to `tnt.register` with the following addition: | ||||||
|  |  * `explode_center` false by default which removes TNT node on blast, when true will explode center node. | ||||||
|  |  | ||||||
| `tnt.burn(position, [nodename])` | `tnt.burn(position, [nodename])` | ||||||
|  |  | ||||||
|   | |||||||
| @@ -49,21 +49,24 @@ function beds.register_bed(name, def) | |||||||
| 			local node = minetest.get_node(under) | 			local node = minetest.get_node(under) | ||||||
| 			local udef = minetest.registered_nodes[node.name] | 			local udef = minetest.registered_nodes[node.name] | ||||||
| 			if udef and udef.on_rightclick and | 			if udef and udef.on_rightclick and | ||||||
| 					not (placer and placer:get_player_control().sneak) then | 					not (placer and placer:is_player() and | ||||||
|  | 					placer:get_player_control().sneak) then | ||||||
| 				return udef.on_rightclick(under, node, placer, itemstack, | 				return udef.on_rightclick(under, node, placer, itemstack, | ||||||
| 					pointed_thing) or itemstack | 					pointed_thing) or itemstack | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			local pos | 			local pos | ||||||
| 			if minetest.registered_items[minetest.get_node(under).name].buildable_to then | 			if udef and udef.buildable_to then | ||||||
| 				pos = under | 				pos = under | ||||||
| 			else | 			else | ||||||
| 				pos = pointed_thing.above | 				pos = pointed_thing.above | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			if minetest.is_protected(pos, placer:get_player_name()) and | 			local player_name = placer and placer:get_player_name() or "" | ||||||
| 					not minetest.check_player_privs(placer, "protection_bypass") then |  | ||||||
| 				minetest.record_protection_violation(pos, placer:get_player_name()) | 			if minetest.is_protected(pos, player_name) and | ||||||
|  | 					not minetest.check_player_privs(player_name, "protection_bypass") then | ||||||
|  | 				minetest.record_protection_violation(pos, player_name) | ||||||
| 				return itemstack | 				return itemstack | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| @@ -72,12 +75,13 @@ function beds.register_bed(name, def) | |||||||
| 				return itemstack | 				return itemstack | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			local dir = minetest.dir_to_facedir(placer:get_look_dir()) | 			local dir = placer and placer:get_look_dir() and | ||||||
|  | 				minetest.dir_to_facedir(placer:get_look_dir()) or 0 | ||||||
| 			local botpos = vector.add(pos, minetest.facedir_to_dir(dir)) | 			local botpos = vector.add(pos, minetest.facedir_to_dir(dir)) | ||||||
|  |  | ||||||
| 			if minetest.is_protected(botpos, placer:get_player_name()) and | 			if minetest.is_protected(botpos, player_name) and | ||||||
| 					not minetest.check_player_privs(placer, "protection_bypass") then | 					not minetest.check_player_privs(player_name, "protection_bypass") then | ||||||
| 				minetest.record_protection_violation(botpos, placer:get_player_name()) | 				minetest.record_protection_violation(botpos, player_name) | ||||||
| 				return itemstack | 				return itemstack | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| @@ -90,7 +94,7 @@ function beds.register_bed(name, def) | |||||||
| 			minetest.set_node(botpos, {name = name .. "_top", param2 = dir}) | 			minetest.set_node(botpos, {name = name .. "_top", param2 = dir}) | ||||||
|  |  | ||||||
| 			if not (creative and creative.is_enabled_for | 			if not (creative and creative.is_enabled_for | ||||||
| 					and creative.is_enabled_for(placer:get_player_name())) then | 					and creative.is_enabled_for(player_name)) then | ||||||
| 				itemstack:take_item() | 				itemstack:take_item() | ||||||
| 			end | 			end | ||||||
| 			return itemstack | 			return itemstack | ||||||
|   | |||||||
| @@ -230,7 +230,8 @@ minetest.register_craftitem("boats:boat", { | |||||||
| 		local node = minetest.get_node(under) | 		local node = minetest.get_node(under) | ||||||
| 		local udef = minetest.registered_nodes[node.name] | 		local udef = minetest.registered_nodes[node.name] | ||||||
| 		if udef and udef.on_rightclick and | 		if udef and udef.on_rightclick and | ||||||
| 				not (placer and placer:get_player_control().sneak) then | 				not (placer and placer:is_player() and | ||||||
|  | 				placer:get_player_control().sneak) then | ||||||
| 			return udef.on_rightclick(under, node, placer, itemstack, | 			return udef.on_rightclick(under, node, placer, itemstack, | ||||||
| 				pointed_thing) or itemstack | 				pointed_thing) or itemstack | ||||||
| 		end | 		end | ||||||
| @@ -244,9 +245,12 @@ minetest.register_craftitem("boats:boat", { | |||||||
| 		pointed_thing.under.y = pointed_thing.under.y + 0.5 | 		pointed_thing.under.y = pointed_thing.under.y + 0.5 | ||||||
| 		boat = minetest.add_entity(pointed_thing.under, "boats:boat") | 		boat = minetest.add_entity(pointed_thing.under, "boats:boat") | ||||||
| 		if boat then | 		if boat then | ||||||
|  | 			if placer then | ||||||
| 				boat:setyaw(placer:get_look_horizontal()) | 				boat:setyaw(placer:get_look_horizontal()) | ||||||
| 			if not (creative and creative.is_enabled_for | 			end | ||||||
| 					and creative.is_enabled_for(placer:get_player_name())) then | 			local player_name = placer and placer:get_player_name() or "" | ||||||
|  | 			if not (creative and creative.is_enabled_for and | ||||||
|  | 					creative.is_enabled_for(player_name)) then | ||||||
| 				itemstack:take_item() | 				itemstack:take_item() | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
|   | |||||||
| @@ -68,6 +68,12 @@ minetest.register_node("bones:bones", { | |||||||
| 	on_metadata_inventory_take = function(pos, listname, index, stack, player) | 	on_metadata_inventory_take = function(pos, listname, index, stack, player) | ||||||
| 		local meta = minetest.get_meta(pos) | 		local meta = minetest.get_meta(pos) | ||||||
| 		if meta:get_inventory():is_empty("main") then | 		if meta:get_inventory():is_empty("main") then | ||||||
|  | 			local inv = player:get_inventory() | ||||||
|  | 			if inv:room_for_item("main", {name = "bones:bones"}) then | ||||||
|  | 				inv:add_item("main", {name = "bones:bones"}) | ||||||
|  | 			else | ||||||
|  | 				minetest.add_item(pos, "bones:bones") | ||||||
|  | 			end | ||||||
| 			minetest.remove_node(pos) | 			minetest.remove_node(pos) | ||||||
| 		end | 		end | ||||||
| 	end, | 	end, | ||||||
|   | |||||||
| @@ -69,7 +69,8 @@ function bucket.register_liquid(source, flowing, itemname, inventory_image, name | |||||||
|  |  | ||||||
| 				-- Call on_rightclick if the pointed node defines it | 				-- Call on_rightclick if the pointed node defines it | ||||||
| 				if ndef and ndef.on_rightclick and | 				if ndef and ndef.on_rightclick and | ||||||
| 				   user and not user:get_player_control().sneak then | 						not (user and user:is_player() and | ||||||
|  | 						user:get_player_control().sneak) then | ||||||
| 					return ndef.on_rightclick( | 					return ndef.on_rightclick( | ||||||
| 						pointed_thing.under, | 						pointed_thing.under, | ||||||
| 						node, user, | 						node, user, | ||||||
|   | |||||||
| @@ -58,7 +58,8 @@ end | |||||||
|  |  | ||||||
| function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) | function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) | ||||||
| 	local pos = self.object:getpos() | 	local pos = self.object:getpos() | ||||||
| 	if not self.railtype then | 	local vel = self.object:getvelocity() | ||||||
|  | 	if not self.railtype or vector.equals(vel, {x=0, y=0, z=0}) then | ||||||
| 		local node = minetest.get_node(pos).name | 		local node = minetest.get_node(pos).name | ||||||
| 		self.railtype = minetest.get_item_group(node, "connect_to_raillike") | 		self.railtype = minetest.get_item_group(node, "connect_to_raillike") | ||||||
| 	end | 	end | ||||||
| @@ -105,7 +106,6 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, | |||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	-- Player punches cart to alter velocity | 	-- Player punches cart to alter velocity | ||||||
| 	local vel = self.object:getvelocity() |  | ||||||
| 	if puncher:get_player_name() == self.driver then | 	if puncher:get_player_name() == self.driver then | ||||||
| 		if math.abs(vel.x + vel.z) > carts.punch_speed_max then | 		if math.abs(vel.x + vel.z) > carts.punch_speed_max then | ||||||
| 			return | 			return | ||||||
| @@ -367,7 +367,8 @@ minetest.register_craftitem("carts:cart", { | |||||||
| 		local node = minetest.get_node(under) | 		local node = minetest.get_node(under) | ||||||
| 		local udef = minetest.registered_nodes[node.name] | 		local udef = minetest.registered_nodes[node.name] | ||||||
| 		if udef and udef.on_rightclick and | 		if udef and udef.on_rightclick and | ||||||
| 				not (placer and placer:get_player_control().sneak) then | 				not (placer and placer:is_player() and | ||||||
|  | 				placer:get_player_control().sneak) then | ||||||
| 			return udef.on_rightclick(under, node, placer, itemstack, | 			return udef.on_rightclick(under, node, placer, itemstack, | ||||||
| 				pointed_thing) or itemstack | 				pointed_thing) or itemstack | ||||||
| 		end | 		end | ||||||
|   | |||||||
| @@ -159,23 +159,29 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) | |||||||
| end | end | ||||||
|  |  | ||||||
| function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) | function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) | ||||||
|  | 	if vector.equals(old_pos, pos_) then | ||||||
|  | 		return true | ||||||
|  | 	end | ||||||
|  |  | ||||||
| 	local pos = vector.round(pos_) | 	local pos = vector.round(pos_) | ||||||
| 	local pf_pos = vector.round(old_pos) | 	local pf_pos = vector.round(old_pos) | ||||||
| 	local pf_dir = vector.new(old_dir) | 	local pf_dir = vector.new(old_dir) | ||||||
|  |  | ||||||
| 	for i = 1, 3 do | 	for i = 1, 3 do | ||||||
| 		if vector.equals(pf_pos, pos) then | 		pf_dir, pf_switch = carts:get_rail_direction( | ||||||
| 			-- Success! Cart moved on correctly | 			pf_pos, pf_dir, ctrl, pf_switch, railtype) | ||||||
| 			return true |  | ||||||
| 		end |  | ||||||
|  |  | ||||||
| 		pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype) |  | ||||||
| 		if vector.equals(pf_dir, {x=0, y=0, z=0}) then | 		if vector.equals(pf_dir, {x=0, y=0, z=0}) then | ||||||
| 			-- No way forwards | 			-- No way forwards | ||||||
| 			return false | 			return false | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		pf_pos = vector.add(pf_pos, pf_dir) | 		pf_pos = vector.add(pf_pos, pf_dir) | ||||||
|  |  | ||||||
|  | 		if vector.equals(pf_pos, pos) then | ||||||
|  | 			-- Success! Cart moved on correctly | ||||||
|  | 			return true | ||||||
|  | 		end | ||||||
| 	end | 	end | ||||||
| 	-- Cart not found | 	-- Cart not found | ||||||
| 	return false | 	return false | ||||||
| @@ -211,7 +217,12 @@ end | |||||||
|  |  | ||||||
| function carts:get_rail_groups(additional_groups) | function carts:get_rail_groups(additional_groups) | ||||||
| 	-- Get the default rail groups and add more when a table is given | 	-- Get the default rail groups and add more when a table is given | ||||||
| 	local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1} | 	local groups = { | ||||||
|  | 		dig_immediate = 2, | ||||||
|  | 		attached_node = 1, | ||||||
|  | 		rail = 1, | ||||||
|  | 		connect_to_raillike = minetest.raillike_group("rail") | ||||||
|  | 	} | ||||||
| 	if type(additional_groups) == "table" then | 	if type(additional_groups) == "table" then | ||||||
| 		for k, v in pairs(additional_groups) do | 		for k, v in pairs(additional_groups) do | ||||||
| 			groups[k] = v | 			groups[k] = v | ||||||
|   | |||||||
| @@ -40,16 +40,16 @@ end | |||||||
|  |  | ||||||
| -- Unlimited node placement | -- Unlimited node placement | ||||||
| minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) | minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) | ||||||
|  | 	if placer and placer:is_player() then | ||||||
| 		return creative.is_enabled_for(placer:get_player_name()) | 		return creative.is_enabled_for(placer:get_player_name()) | ||||||
|  | 	end | ||||||
| end) | end) | ||||||
|  |  | ||||||
| -- Don't pick up if the item is already in the inventory | -- Don't pick up if the item is already in the inventory | ||||||
| local old_handle_node_drops = minetest.handle_node_drops | local old_handle_node_drops = minetest.handle_node_drops | ||||||
| function minetest.handle_node_drops(pos, drops, digger) | function minetest.handle_node_drops(pos, drops, digger) | ||||||
| 	if not digger or not digger:is_player() then | 	if not digger or not digger:is_player() or | ||||||
| 		return | 		not creative.is_enabled_for(digger:get_player_name()) then | ||||||
| 	end |  | ||||||
| 	if not creative.is_enabled_for(digger:get_player_name()) then |  | ||||||
| 		return old_handle_node_drops(pos, drops, digger) | 		return old_handle_node_drops(pos, drops, digger) | ||||||
| 	end | 	end | ||||||
| 	local inv = digger:get_inventory() | 	local inv = digger:get_inventory() | ||||||
|   | |||||||
| @@ -1,4 +1,19 @@ | |||||||
| local player_inventory = {} | local player_inventory = {} | ||||||
|  | local inventory_cache = {} | ||||||
|  |  | ||||||
|  | local function init_creative_cache(items) | ||||||
|  | 	inventory_cache[items] = {} | ||||||
|  | 	local i_cache = inventory_cache[items] | ||||||
|  |  | ||||||
|  | 	for name, def in pairs(items) do | ||||||
|  | 		if def.groups.not_in_creative_inventory ~= 1 and | ||||||
|  | 				def.description and def.description ~= "" then | ||||||
|  | 			i_cache[name] = def | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 	table.sort(i_cache) | ||||||
|  | 	return i_cache | ||||||
|  | end | ||||||
|  |  | ||||||
| function creative.init_creative_inventory(player) | function creative.init_creative_inventory(player) | ||||||
| 	local player_name = player:get_player_name() | 	local player_name = player:get_player_name() | ||||||
| @@ -10,22 +25,25 @@ function creative.init_creative_inventory(player) | |||||||
|  |  | ||||||
| 	minetest.create_detached_inventory("creative_" .. player_name, { | 	minetest.create_detached_inventory("creative_" .. player_name, { | ||||||
| 		allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2) | 		allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2) | ||||||
| 			if not to_list == "main" then | 			local name = player2 and player2:get_player_name() or "" | ||||||
| 				return count | 			if not creative.is_enabled_for(name) or | ||||||
| 			else | 					to_list == "main" then | ||||||
| 				return 0 | 				return 0 | ||||||
| 			end | 			end | ||||||
|  | 			return count | ||||||
| 		end, | 		end, | ||||||
| 		allow_put = function(inv, listname, index, stack, player2) | 		allow_put = function(inv, listname, index, stack, player2) | ||||||
| 			return 0 | 			return 0 | ||||||
| 		end, | 		end, | ||||||
| 		allow_take = function(inv, listname, index, stack, player2) | 		allow_take = function(inv, listname, index, stack, player2) | ||||||
|  | 			local name = player2 and player2:get_player_name() or "" | ||||||
|  | 			if not creative.is_enabled_for(name) then | ||||||
|  | 				return 0 | ||||||
|  | 			end | ||||||
| 			return -1 | 			return -1 | ||||||
| 		end, | 		end, | ||||||
| 		on_move = function(inv, from_list, from_index, to_list, to_index, count, player2) | 		on_move = function(inv, from_list, from_index, to_list, to_index, count, player2) | ||||||
| 		end, | 		end, | ||||||
| 		on_put = function(inv, listname, index, stack, player2) |  | ||||||
| 		end, |  | ||||||
| 		on_take = function(inv, listname, index, stack, player2) | 		on_take = function(inv, listname, index, stack, player2) | ||||||
| 			if stack and stack:get_count() > 0 then | 			if stack and stack:get_count() > 0 then | ||||||
| 				minetest.log("action", player_name .. " takes " .. stack:get_name().. " from creative inventory") | 				minetest.log("action", player_name .. " takes " .. stack:get_name().. " from creative inventory") | ||||||
| @@ -42,11 +60,11 @@ function creative.update_creative_inventory(player_name, tab_content) | |||||||
| 			creative.init_creative_inventory(minetest.get_player_by_name(player_name)) | 			creative.init_creative_inventory(minetest.get_player_by_name(player_name)) | ||||||
| 	local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name}) | 	local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name}) | ||||||
|  |  | ||||||
| 	for name, def in pairs(tab_content) do | 	local items = inventory_cache[tab_content] or init_creative_cache(tab_content) | ||||||
| 		if not (def.groups.not_in_creative_inventory == 1) and |  | ||||||
| 				def.description and def.description ~= "" and | 	for name, def in pairs(items) do | ||||||
| 				(def.name:find(inv.filter, 1, true) or | 		if def.name:find(inv.filter, 1, true) or | ||||||
| 					def.description:lower():find(inv.filter, 1, true)) then | 				def.description:lower():find(inv.filter, 1, true) then | ||||||
| 			creative_list[#creative_list+1] = name | 			creative_list[#creative_list+1] = name | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -100,6 +118,8 @@ function creative.register_tab(name, title, items) | |||||||
| 					button[2.75,3.4;0.8,0.5;creative_clear;X] | 					button[2.75,3.4;0.8,0.5;creative_clear;X] | ||||||
| 					tooltip[creative_search;Search] | 					tooltip[creative_search;Search] | ||||||
| 					tooltip[creative_clear;Reset] | 					tooltip[creative_clear;Reset] | ||||||
|  | 					tooltip[creative_prev;Previous page] | ||||||
|  | 					tooltip[creative_next;Next page] | ||||||
| 					listring[current_player;main] | 					listring[current_player;main] | ||||||
| 					field_close_on_enter[creative_filter;false] | 					field_close_on_enter[creative_filter;false] | ||||||
| 				]] .. | 				]] .. | ||||||
| @@ -158,10 +178,6 @@ function creative.register_tab(name, title, items) | |||||||
| 	}) | 	}) | ||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_on_joinplayer(function(player) |  | ||||||
| 	creative.update_creative_inventory(player:get_player_name(), minetest.registered_items) |  | ||||||
| end) |  | ||||||
|  |  | ||||||
| creative.register_tab("all", "All", minetest.registered_items) | creative.register_tab("all", "All", minetest.registered_items) | ||||||
| creative.register_tab("nodes", "Nodes", minetest.registered_nodes) | creative.register_tab("nodes", "Nodes", minetest.registered_nodes) | ||||||
| creative.register_tab("tools", "Tools", minetest.registered_tools) | creative.register_tab("tools", "Tools", minetest.registered_tools) | ||||||
|   | |||||||
| @@ -119,6 +119,7 @@ paramat (CC BY-SA 3.0): | |||||||
|   default_silver_sandstone.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) |   default_silver_sandstone.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) | ||||||
|   default_silver_sandstone_brick.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) |   default_silver_sandstone_brick.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) | ||||||
|   default_silver_sandstone_block.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) |   default_silver_sandstone_block.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) | ||||||
|  |   default_bookshelf_slot.png -- Derived from a texture by Gambit (CC-BY-SA 3.0) | ||||||
|  |  | ||||||
| brunob.santos (CC BY-SA 4.0): | brunob.santos (CC BY-SA 4.0): | ||||||
|   default_desert_cobble.png |   default_desert_cobble.png | ||||||
| @@ -131,7 +132,6 @@ BlockMen (CC BY-SA 3.0): | |||||||
|   default_gold_ingot.png |   default_gold_ingot.png | ||||||
|   default_tool_steelsword.png |   default_tool_steelsword.png | ||||||
|   default_diamond.png |   default_diamond.png | ||||||
|   default_book.png |  | ||||||
|   default_tool_*.png |   default_tool_*.png | ||||||
|   default_lava_source_animated.png |   default_lava_source_animated.png | ||||||
|   default_lava_flowing_animated.png |   default_lava_flowing_animated.png | ||||||
| @@ -145,11 +145,7 @@ BlockMen (CC BY-SA 3.0): | |||||||
|   bubble.png |   bubble.png | ||||||
|   gui_*.png |   gui_*.png | ||||||
|  |  | ||||||
| Wuzzy (CC BY-SA 3.0): |  | ||||||
|   default_bookshelf_slot.png (based on default_book.png) |  | ||||||
|  |  | ||||||
| sofar (CC BY-SA 3.0): | sofar (CC BY-SA 3.0): | ||||||
|   default_book_written.png, based on default_book.png |  | ||||||
|   default_aspen_sapling |   default_aspen_sapling | ||||||
|   default_aspen_tree |   default_aspen_tree | ||||||
|   default_aspen_tree_top, derived from default_pine_tree_top (by paramat) |   default_aspen_tree_top, derived from default_pine_tree_top (by paramat) | ||||||
| @@ -186,6 +182,7 @@ Gambit (CC BY-SA 3.0): | |||||||
|   default_snowball.png |   default_snowball.png | ||||||
|   default_key.png |   default_key.png | ||||||
|   default_key_skeleton.png |   default_key_skeleton.png | ||||||
|  |   default_book.png | ||||||
|  |  | ||||||
| asl97 (CC BY-SA 3.0): | asl97 (CC BY-SA 3.0): | ||||||
|   default_ice.png |   default_ice.png | ||||||
| @@ -221,6 +218,9 @@ kilbith (CC BY-SA 3.0): | |||||||
|   default_tin_ingot.png |   default_tin_ingot.png | ||||||
|   default_tin_lump.png |   default_tin_lump.png | ||||||
|  |  | ||||||
|  | CloudyProton (CC BY-SA 3.0): | ||||||
|  |   default_book_written.png, based on default_book.png by Gambit | ||||||
|  |  | ||||||
| Glass breaking sounds (CC BY 3.0): | Glass breaking sounds (CC BY 3.0): | ||||||
|   1: http://www.freesound.org/people/cmusounddesign/sounds/71947/ |   1: http://www.freesound.org/people/cmusounddesign/sounds/71947/ | ||||||
|   2: http://www.freesound.org/people/Tomlija/sounds/97669/ |   2: http://www.freesound.org/people/Tomlija/sounds/97669/ | ||||||
|   | |||||||
| @@ -190,6 +190,9 @@ minetest.register_craft({ | |||||||
| 	} | 	} | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | -- Axes | ||||||
|  | -- Recipes face left to match appearence in textures and inventory | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	output = 'default:axe_wood', | 	output = 'default:axe_wood', | ||||||
| 	recipe = { | 	recipe = { | ||||||
| @@ -244,60 +247,6 @@ minetest.register_craft({ | |||||||
| 	} | 	} | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	output = 'default:axe_wood', |  | ||||||
| 	recipe = { |  | ||||||
| 		{'group:wood', 'group:wood'}, |  | ||||||
| 		{'group:stick', 'group:wood'}, |  | ||||||
| 		{'group:stick',''}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	output = 'default:axe_stone', |  | ||||||
| 	recipe = { |  | ||||||
| 		{'group:stone', 'group:stone'}, |  | ||||||
| 		{'group:stick', 'group:stone'}, |  | ||||||
| 		{'group:stick', ''}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	output = 'default:axe_steel', |  | ||||||
| 	recipe = { |  | ||||||
| 		{'default:steel_ingot', 'default:steel_ingot'}, |  | ||||||
| 		{'group:stick', 'default:steel_ingot'}, |  | ||||||
| 		{'group:stick', ''}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	output = 'default:axe_bronze', |  | ||||||
| 	recipe = { |  | ||||||
| 		{'default:bronze_ingot', 'default:bronze_ingot'}, |  | ||||||
| 		{'group:stick', 'default:bronze_ingot'}, |  | ||||||
| 		{'group:stick', ''}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	output = 'default:axe_mese', |  | ||||||
| 	recipe = { |  | ||||||
| 		{'default:mese_crystal', 'default:mese_crystal'}, |  | ||||||
| 		{'group:stick', 'default:mese_crystal'}, |  | ||||||
| 		{'group:stick', ''}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	output = 'default:axe_diamond', |  | ||||||
| 	recipe = { |  | ||||||
| 		{'default:diamond', 'default:diamond'}, |  | ||||||
| 		{'group:stick', 'default:diamond'}, |  | ||||||
| 		{'group:stick', ''}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	output = 'default:sword_wood', | 	output = 'default:sword_wood', | ||||||
| 	recipe = { | 	recipe = { | ||||||
| @@ -904,7 +853,7 @@ minetest.register_craft({ | |||||||
| -- Fuels | -- Fuels | ||||||
| -- | -- | ||||||
|  |  | ||||||
| -- Support use of group:tree | -- Support use of group:tree, includes default:tree which has the same burn time | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "group:tree", | 	recipe = "group:tree", | ||||||
| @@ -927,12 +876,6 @@ minetest.register_craft({ | |||||||
| 	burntime = 26, | 	burntime = 26, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	type = "fuel", |  | ||||||
| 	recipe = "default:tree", |  | ||||||
| 	burntime = 30, |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:acacia_tree", | 	recipe = "default:acacia_tree", | ||||||
| @@ -946,7 +889,7 @@ minetest.register_craft({ | |||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Support use of group:wood | -- Support use of group:wood, includes default:wood which has the same burn time | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "group:wood", | 	recipe = "group:wood", | ||||||
| @@ -965,12 +908,6 @@ minetest.register_craft({ | |||||||
| 	burntime = 6, | 	burntime = 6, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	type = "fuel", |  | ||||||
| 	recipe = "default:wood", |  | ||||||
| 	burntime = 7, |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:acacia_wood", | 	recipe = "default:acacia_wood", | ||||||
| @@ -984,53 +921,47 @@ minetest.register_craft({ | |||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Support use of group:sapling | -- Support use of group:sapling, includes default:sapling which has the same burn time | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "group:sapling", | 	recipe = "group:sapling", | ||||||
| 	burntime = 10, | 	burntime = 5, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:bush_sapling", | 	recipe = "default:bush_sapling", | ||||||
| 	burntime = 6, | 	burntime = 3, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:acacia_bush_sapling", | 	recipe = "default:acacia_bush_sapling", | ||||||
| 	burntime = 7, | 	burntime = 4, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:aspen_sapling", | 	recipe = "default:aspen_sapling", | ||||||
| 	burntime = 8, | 	burntime = 4, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:pine_sapling", | 	recipe = "default:pine_sapling", | ||||||
| 	burntime = 9, | 	burntime = 5, | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	type = "fuel", |  | ||||||
| 	recipe = "default:sapling", |  | ||||||
| 	burntime = 10, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:acacia_sapling", | 	recipe = "default:acacia_sapling", | ||||||
| 	burntime = 11, | 	burntime = 6, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:junglesapling", | 	recipe = "default:junglesapling", | ||||||
| 	burntime = 12, | 	burntime = 6, | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1080,13 +1011,13 @@ minetest.register_craft({ | |||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:junglegrass", | 	recipe = "default:junglegrass", | ||||||
| 	burntime = 2, | 	burntime = 3, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "group:leaves", | 	recipe = "group:leaves", | ||||||
| 	burntime = 1, | 	burntime = 4, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| @@ -1098,7 +1029,7 @@ minetest.register_craft({ | |||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:papyrus", | 	recipe = "default:papyrus", | ||||||
| 	burntime = 1, | 	burntime = 3, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| @@ -1110,7 +1041,7 @@ minetest.register_craft({ | |||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:ladder_wood", | 	recipe = "default:ladder_wood", | ||||||
| 	burntime = 2, | 	burntime = 7, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| @@ -1143,12 +1074,6 @@ minetest.register_craft({ | |||||||
| 	burntime = 30, | 	burntime = 30, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ |  | ||||||
| 	type = "fuel", |  | ||||||
| 	recipe = "default:apple", |  | ||||||
| 	burntime = 3, |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	type = "fuel", | 	type = "fuel", | ||||||
| 	recipe = "default:coal_lump", | 	recipe = "default:coal_lump", | ||||||
|   | |||||||
| @@ -75,12 +75,16 @@ local function book_on_use(itemstack, user) | |||||||
| 	return itemstack | 	return itemstack | ||||||
| end | end | ||||||
|  |  | ||||||
|  | local max_text_size = 10000 | ||||||
|  | local max_title_size = 80 | ||||||
|  | local short_title_size = 35 | ||||||
| minetest.register_on_player_receive_fields(function(player, formname, fields) | minetest.register_on_player_receive_fields(function(player, formname, fields) | ||||||
| 	if formname ~= "default:book" then return end | 	if formname ~= "default:book" then return end | ||||||
| 	local inv = player:get_inventory() | 	local inv = player:get_inventory() | ||||||
| 	local stack = player:get_wielded_item() | 	local stack = player:get_wielded_item() | ||||||
|  |  | ||||||
| 	if fields.save and fields.title ~= "" and fields.text ~= "" then | 	if fields.save and fields.title and fields.text | ||||||
|  | 			and fields.title ~= "" and fields.text ~= "" then | ||||||
| 		local new_stack, data | 		local new_stack, data | ||||||
| 		if stack:get_name() ~= "default:book_written" then | 		if stack:get_name() ~= "default:book_written" then | ||||||
| 			local count = stack:get_count() | 			local count = stack:get_count() | ||||||
| @@ -99,11 +103,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) | |||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		if not data then data = {} end | 		if not data then data = {} end | ||||||
| 		data.title = fields.title | 		data.title = fields.title:sub(1, max_title_size) | ||||||
| 		data.owner = player:get_player_name() | 		data.owner = player:get_player_name() | ||||||
| 		data.description = "\""..fields.title.."\" by "..data.owner | 		local short_title = data.title | ||||||
| 		data.text = fields.text | 		-- Don't bother triming the title if the trailing dots would make it longer | ||||||
| 		data.text_len = #data.text | 		if #short_title > short_title_size + 3 then | ||||||
|  | 			short_title = short_title:sub(1, short_title_size) .. "..." | ||||||
|  | 		end | ||||||
|  | 		data.description = "\""..short_title.."\" by "..data.owner | ||||||
|  | 		data.text = fields.text:sub(1, max_text_size) | ||||||
|  | 		data.text = data.text:gsub("\r\n", "\n"):gsub("\r", "\n") | ||||||
| 		data.page = 1 | 		data.page = 1 | ||||||
| 		data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp) | 		data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -136,10 +136,12 @@ if minetest.settings:get_bool("enable_lavacooling") ~= false then | |||||||
| 		label = "Lava cooling", | 		label = "Lava cooling", | ||||||
| 		nodenames = {"default:lava_source", "default:lava_flowing"}, | 		nodenames = {"default:lava_source", "default:lava_flowing"}, | ||||||
| 		neighbors = {"group:cools_lava", "group:water"}, | 		neighbors = {"group:cools_lava", "group:water"}, | ||||||
| 		interval = 1, | 		interval = 2, | ||||||
| 		chance = 2, | 		chance = 2, | ||||||
| 		catch_up = false, | 		catch_up = false, | ||||||
| 		action = default.cool_lava, | 		action = function(...) | ||||||
|  | 			default.cool_lava(...) | ||||||
|  | 		end, | ||||||
| 	}) | 	}) | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -222,7 +224,9 @@ minetest.register_abm({ | |||||||
| 	neighbors = {"group:sand"}, | 	neighbors = {"group:sand"}, | ||||||
| 	interval = 12, | 	interval = 12, | ||||||
| 	chance = 83, | 	chance = 83, | ||||||
| 	action = default.grow_cactus | 	action = function(...) | ||||||
|  | 		default.grow_cactus(...) | ||||||
|  | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_abm({ | minetest.register_abm({ | ||||||
| @@ -231,7 +235,9 @@ minetest.register_abm({ | |||||||
| 	neighbors = {"default:dirt", "default:dirt_with_grass"}, | 	neighbors = {"default:dirt", "default:dirt_with_grass"}, | ||||||
| 	interval = 14, | 	interval = 14, | ||||||
| 	chance = 71, | 	chance = 71, | ||||||
| 	action = default.grow_papyrus | 	action = function(...) | ||||||
|  | 		default.grow_papyrus(...) | ||||||
|  | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -291,7 +297,7 @@ function default.register_fence(name, def) | |||||||
| 		groups = {}, | 		groups = {}, | ||||||
| 	} | 	} | ||||||
| 	for k, v in pairs(default_fields) do | 	for k, v in pairs(default_fields) do | ||||||
| 		if not def[k] then | 		if def[k] == nil then | ||||||
| 			def[k] = v | 			def[k] = v | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -313,7 +319,7 @@ end | |||||||
| -- Prevent decay of placed leaves | -- Prevent decay of placed leaves | ||||||
|  |  | ||||||
| default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) | default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) | ||||||
| 	if placer and not placer:get_player_control().sneak then | 	if placer and placer:is_player() and not placer:get_player_control().sneak then | ||||||
| 		local node = minetest.get_node(pos) | 		local node = minetest.get_node(pos) | ||||||
| 		node.param2 = 1 | 		node.param2 = 1 | ||||||
| 		minetest.set_node(pos, node) | 		minetest.set_node(pos, node) | ||||||
|   | |||||||
| @@ -119,7 +119,7 @@ local function furnace_node_timer(pos, elapsed) | |||||||
| 	local fuel | 	local fuel | ||||||
|  |  | ||||||
| 	local update = true | 	local update = true | ||||||
| 	while update do | 	while elapsed > 0 and update do | ||||||
| 		update = false | 		update = false | ||||||
|  |  | ||||||
| 		srclist = inv:get_list("src") | 		srclist = inv:get_list("src") | ||||||
| @@ -134,13 +134,18 @@ local function furnace_node_timer(pos, elapsed) | |||||||
| 		cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) | 		cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) | ||||||
| 		cookable = cooked.time ~= 0 | 		cookable = cooked.time ~= 0 | ||||||
|  |  | ||||||
|  | 		local el = math.min(elapsed, fuel_totaltime - fuel_time) | ||||||
|  | 		if cookable then -- fuel lasts long enough, adjust el to cooking duration | ||||||
|  | 			el = math.min(el, cooked.time - src_time) | ||||||
|  | 		end | ||||||
|  |  | ||||||
| 		-- Check if we have enough fuel to burn | 		-- Check if we have enough fuel to burn | ||||||
| 		if fuel_time < fuel_totaltime then | 		if fuel_time < fuel_totaltime then | ||||||
| 			-- The furnace is currently active and has enough fuel | 			-- The furnace is currently active and has enough fuel | ||||||
| 			fuel_time = fuel_time + elapsed | 			fuel_time = fuel_time + el | ||||||
| 			-- If there is a cookable item then check if it is ready yet | 			-- If there is a cookable item then check if it is ready yet | ||||||
| 			if cookable then | 			if cookable then | ||||||
| 				src_time = src_time + elapsed | 				src_time = src_time + el | ||||||
| 				if src_time >= cooked.time then | 				if src_time >= cooked.time then | ||||||
| 					-- Place result in dst list if possible | 					-- Place result in dst list if possible | ||||||
| 					if inv:room_for_item("dst", cooked.item) then | 					if inv:room_for_item("dst", cooked.item) then | ||||||
| @@ -149,6 +154,9 @@ local function furnace_node_timer(pos, elapsed) | |||||||
| 						src_time = src_time - cooked.time | 						src_time = src_time - cooked.time | ||||||
| 						update = true | 						update = true | ||||||
| 					end | 					end | ||||||
|  | 				else | ||||||
|  | 					-- Item could not be cooked: probably missing fuel | ||||||
|  | 					update = true | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| 		else | 		else | ||||||
| @@ -166,8 +174,7 @@ local function furnace_node_timer(pos, elapsed) | |||||||
| 					-- Take fuel from fuel list | 					-- Take fuel from fuel list | ||||||
| 					inv:set_stack("fuel", 1, afterfuel.items[1]) | 					inv:set_stack("fuel", 1, afterfuel.items[1]) | ||||||
| 					update = true | 					update = true | ||||||
| 					fuel_totaltime = fuel.time + (fuel_time - fuel_totaltime) | 					fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time) | ||||||
| 					src_time = src_time + elapsed |  | ||||||
| 				end | 				end | ||||||
| 			else | 			else | ||||||
| 				-- We don't need to get new fuel since there is no cookable item | 				-- We don't need to get new fuel since there is no cookable item | ||||||
| @@ -177,7 +184,7 @@ local function furnace_node_timer(pos, elapsed) | |||||||
| 			fuel_time = 0 | 			fuel_time = 0 | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		elapsed = 0 | 		elapsed = elapsed - el | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if fuel and fuel_totaltime > fuel.time then | 	if fuel and fuel_totaltime > fuel.time then | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ Licenses of media (textures, models and sounds) | |||||||
| ----------------------------------------------- | ----------------------------------------------- | ||||||
|  |  | ||||||
| Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) | Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) | ||||||
| Copyright (C) 2010-2016: | Copyright (C) 2010-2017: | ||||||
|   celeron55, Perttu Ahola <celeron55@gmail.com> |   celeron55, Perttu Ahola <celeron55@gmail.com> | ||||||
|   Cisoun |   Cisoun | ||||||
|   G4JC |   G4JC | ||||||
| @@ -44,6 +44,7 @@ Copyright (C) 2010-2016: | |||||||
|   GreenXenith |   GreenXenith | ||||||
|   kaeza |   kaeza | ||||||
|   kilbith |   kilbith | ||||||
|  |   CloudyProton | ||||||
|  |  | ||||||
| You are free to: | You are free to: | ||||||
| Share — copy and redistribute the material in any medium or format. | Share — copy and redistribute the material in any medium or format. | ||||||
| @@ -111,7 +112,6 @@ http://creativecommons.org/licenses/by-sa/4.0/ | |||||||
| Attribution-ShareAlike 2.0 Generic (CC BY-SA 2.0) | Attribution-ShareAlike 2.0 Generic (CC BY-SA 2.0) | ||||||
| Copyright (C) 2014-2016 Neuromancer | Copyright (C) 2014-2016 Neuromancer | ||||||
|  |  | ||||||
|  |  | ||||||
| You are free to: | You are free to: | ||||||
| Share — copy and redistribute the material in any medium or format. | Share — copy and redistribute the material in any medium or format. | ||||||
| Adapt — remix, transform, and build upon the material for any purpose, even commercially. | Adapt — remix, transform, and build upon the material for any purpose, even commercially. | ||||||
|   | |||||||
| @@ -440,7 +440,7 @@ minetest.register_node("default:dirt_with_snow", { | |||||||
| 	tiles = {"default_snow.png", "default_dirt.png", | 	tiles = {"default_snow.png", "default_dirt.png", | ||||||
| 		{name = "default_dirt.png^default_snow_side.png", | 		{name = "default_dirt.png^default_snow_side.png", | ||||||
| 			tileable_vertical = false}}, | 			tileable_vertical = false}}, | ||||||
| 	groups = {crumbly = 3, spreading_dirt_type = 1, snowy = 1}, | 	groups = {crumbly = 3, soil = 1, spreading_dirt_type = 1, snowy = 1}, | ||||||
| 	drop = 'default:dirt', | 	drop = 'default:dirt', | ||||||
| 	sounds = default.node_sound_dirt_defaults({ | 	sounds = default.node_sound_dirt_defaults({ | ||||||
| 		footstep = {name = "default_snow_footstep", gain = 0.15}, | 		footstep = {name = "default_snow_footstep", gain = 0.15}, | ||||||
| @@ -608,7 +608,7 @@ minetest.register_node("default:sapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(2400,4800)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -673,9 +673,7 @@ minetest.register_node("default:apple", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	after_place_node = function(pos, placer, itemstack) | 	after_place_node = function(pos, placer, itemstack) | ||||||
| 		if placer:is_player() then |  | ||||||
| 		minetest.set_node(pos, {name = "default:apple", param2 = 1}) | 		minetest.set_node(pos, {name = "default:apple", param2 = 1}) | ||||||
| 		end |  | ||||||
| 	end, | 	end, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -742,7 +740,7 @@ minetest.register_node("default:junglesapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(2400,4800)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -821,7 +819,7 @@ minetest.register_node("default:pine_sapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(2400,4800)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -901,7 +899,7 @@ minetest.register_node("default:acacia_sapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(2400,4800)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -979,7 +977,7 @@ minetest.register_node("default:aspen_sapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(2400,4800)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -1362,7 +1360,7 @@ minetest.register_node("default:bush_sapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(1200, 2400)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -1433,7 +1431,7 @@ minetest.register_node("default:acacia_bush_sapling", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
|  |  | ||||||
| 	on_construct = function(pos) | 	on_construct = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(1200, 2400)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end, | 	end, | ||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| @@ -1786,10 +1784,11 @@ local function chest_lid_obstructed(pos) | |||||||
| 	local above = {x = pos.x, y = pos.y + 1, z = pos.z} | 	local above = {x = pos.x, y = pos.y + 1, z = pos.z} | ||||||
| 	local def = minetest.registered_nodes[minetest.get_node(above).name] | 	local def = minetest.registered_nodes[minetest.get_node(above).name] | ||||||
| 	-- allow ladders, signs, wallmounted things and torches to not obstruct | 	-- allow ladders, signs, wallmounted things and torches to not obstruct | ||||||
| 	if def.drawtype == "airlike" or | 	if def and | ||||||
|  | 			(def.drawtype == "airlike" or | ||||||
| 			def.drawtype == "signlike" or | 			def.drawtype == "signlike" or | ||||||
| 			def.drawtype == "torchlike" or | 			def.drawtype == "torchlike" or | ||||||
| 			(def.drawtype == "nodebox" and def.paramtype2 == "wallmounted") then | 			(def.drawtype == "nodebox" and def.paramtype2 == "wallmounted")) then | ||||||
| 		return false | 		return false | ||||||
| 	end | 	end | ||||||
| 	return true | 	return true | ||||||
| @@ -1797,6 +1796,24 @@ end | |||||||
|  |  | ||||||
| local open_chests = {} | local open_chests = {} | ||||||
|  |  | ||||||
|  | local function chest_lid_close(pn) | ||||||
|  | 	local pos = open_chests[pn].pos | ||||||
|  | 	local sound = open_chests[pn].sound | ||||||
|  | 	local swap = open_chests[pn].swap | ||||||
|  |  | ||||||
|  | 	open_chests[pn] = nil | ||||||
|  | 	for k, v in pairs(open_chests) do | ||||||
|  | 		if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then | ||||||
|  | 			return true | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  |  | ||||||
|  | 	local node = minetest.get_node(pos) | ||||||
|  | 	minetest.after(0.2, minetest.swap_node, pos, { name = "default:" .. swap, | ||||||
|  | 			param2 = node.param2 }) | ||||||
|  | 	minetest.sound_play(sound, {gain = 0.3, pos = pos, max_hear_distance = 10}) | ||||||
|  | end | ||||||
|  |  | ||||||
| minetest.register_on_player_receive_fields(function(player, formname, fields) | minetest.register_on_player_receive_fields(function(player, formname, fields) | ||||||
| 	if formname ~= "default:chest" then | 	if formname ~= "default:chest" then | ||||||
| 		return | 		return | ||||||
| @@ -1810,21 +1827,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) | |||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	local pos = open_chests[pn].pos | 	chest_lid_close(pn) | ||||||
| 	local sound = open_chests[pn].sound | 	return true | ||||||
| 	local swap = open_chests[pn].swap | end) | ||||||
| 	local node = minetest.get_node(pos) |  | ||||||
|  |  | ||||||
| 	open_chests[pn] = nil | minetest.register_on_leaveplayer(function(player) | ||||||
| 	for k, v in pairs(open_chests) do | 	local pn = player:get_player_name() | ||||||
| 		if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then | 	if open_chests[pn] then | ||||||
| 			return true | 		chest_lid_close(pn) | ||||||
| 	end | 	end | ||||||
| 	end |  | ||||||
| 	minetest.after(0.2, minetest.swap_node, pos, { name = "default:" .. swap, |  | ||||||
| 			param2 = node.param2 }) |  | ||||||
| 	minetest.sound_play(sound, {gain = 0.3, pos = pos, max_hear_distance = 10}) |  | ||||||
| 	return true |  | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function default.register_chest(name, d) | function default.register_chest(name, d) | ||||||
| @@ -1960,6 +1971,13 @@ function default.register_chest(name, d) | |||||||
| 			open_chests[clicker:get_player_name()] = { pos = pos, | 			open_chests[clicker:get_player_name()] = { pos = pos, | ||||||
| 					sound = def.sound_close, swap = name } | 					sound = def.sound_close, swap = name } | ||||||
| 		end | 		end | ||||||
|  | 		def.on_blast = function(pos) | ||||||
|  | 			local drops = {} | ||||||
|  | 			default.get_inventory_drops(pos, "main", drops) | ||||||
|  | 			drops[#drops+1] = "default:" .. name | ||||||
|  | 			minetest.remove_node(pos) | ||||||
|  | 			return drops | ||||||
|  | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	def.on_metadata_inventory_move = function(pos, from_list, from_index, | 	def.on_metadata_inventory_move = function(pos, from_list, from_index, | ||||||
| @@ -1977,18 +1995,18 @@ function default.register_chest(name, d) | |||||||
| 			" takes " .. stack:get_name() .. | 			" takes " .. stack:get_name() .. | ||||||
| 			" from chest at " .. minetest.pos_to_string(pos)) | 			" from chest at " .. minetest.pos_to_string(pos)) | ||||||
| 	end | 	end | ||||||
| 	def.on_blast = function(pos) |  | ||||||
| 		local drops = {} |  | ||||||
| 		default.get_inventory_drops(pos, "main", drops) |  | ||||||
| 		drops[#drops+1] = "default:chest" |  | ||||||
| 		minetest.remove_node(pos) |  | ||||||
| 		return drops |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	local def_opened = table.copy(def) | 	local def_opened = table.copy(def) | ||||||
| 	local def_closed = table.copy(def) | 	local def_closed = table.copy(def) | ||||||
|  |  | ||||||
| 	def_opened.mesh = "chest_open.obj" | 	def_opened.mesh = "chest_open.obj" | ||||||
|  | 	for i = 1, #def_opened.tiles do | ||||||
|  | 		if type(def_opened.tiles[i]) == "string" then | ||||||
|  | 			def_opened.tiles[i] = {name = def_opened.tiles[i], backface_culling = true} | ||||||
|  | 		elseif def_opened.tiles[i].backface_culling == nil then | ||||||
|  | 			def_opened.tiles[i].backface_culling = true | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
| 	def_opened.drop = "default:" .. name | 	def_opened.drop = "default:" .. name | ||||||
| 	def_opened.groups.not_in_creative_inventory = 1 | 	def_opened.groups.not_in_creative_inventory = 1 | ||||||
| 	def_opened.selection_box = { | 	def_opened.selection_box = { | ||||||
| @@ -1998,6 +2016,7 @@ function default.register_chest(name, d) | |||||||
| 	def_opened.can_dig = function() | 	def_opened.can_dig = function() | ||||||
| 		return false | 		return false | ||||||
| 	end | 	end | ||||||
|  | 	def_opened.on_blast = function() end | ||||||
|  |  | ||||||
| 	def_closed.mesh = nil | 	def_closed.mesh = nil | ||||||
| 	def_closed.drawtype = nil | 	def_closed.drawtype = nil | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 204 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 262 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 191 B After Width: | Height: | Size: 140 B | 
| @@ -389,7 +389,8 @@ minetest.register_tool("default:key", { | |||||||
| 		local node = minetest.get_node(under) | 		local node = minetest.get_node(under) | ||||||
| 		local def = minetest.registered_nodes[node.name] | 		local def = minetest.registered_nodes[node.name] | ||||||
| 		if def and def.on_rightclick and | 		if def and def.on_rightclick and | ||||||
| 				not (placer and placer:get_player_control().sneak) then | 				not (placer and placer:is_player() and | ||||||
|  | 				placer:get_player_control().sneak) then | ||||||
| 			return def.on_rightclick(under, node, placer, itemstack, | 			return def.on_rightclick(under, node, placer, itemstack, | ||||||
| 				pointed_thing) or itemstack | 				pointed_thing) or itemstack | ||||||
| 		end | 		end | ||||||
|   | |||||||
| @@ -63,7 +63,8 @@ minetest.register_node("default:torch", { | |||||||
| 		local node = minetest.get_node(under) | 		local node = minetest.get_node(under) | ||||||
| 		local def = minetest.registered_nodes[node.name] | 		local def = minetest.registered_nodes[node.name] | ||||||
| 		if def and def.on_rightclick and | 		if def and def.on_rightclick and | ||||||
| 			((not placer) or (placer and not placer:get_player_control().sneak)) then | 			not (placer and placer:is_player() and | ||||||
|  | 			placer:get_player_control().sneak) then | ||||||
| 			return def.on_rightclick(under, node, placer, itemstack, | 			return def.on_rightclick(under, node, placer, itemstack, | ||||||
| 				pointed_thing) or itemstack | 				pointed_thing) or itemstack | ||||||
| 		end | 		end | ||||||
|   | |||||||
| @@ -31,12 +31,12 @@ local function is_snow_nearby(pos) | |||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Sapling ABM | -- Grow sapling | ||||||
|  |  | ||||||
| function default.grow_sapling(pos) | function default.grow_sapling(pos) | ||||||
| 	if not default.can_grow(pos) then | 	if not default.can_grow(pos) then | ||||||
| 		-- try a bit later again | 		-- try again 5 min later | ||||||
| 		minetest.get_node_timer(pos):start(math.random(240, 600)) | 		minetest.get_node_timer(pos):start(300) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -94,7 +94,7 @@ minetest.register_lbm({ | |||||||
| 			"default:pine_sapling", "default:acacia_sapling", | 			"default:pine_sapling", "default:acacia_sapling", | ||||||
| 			"default:aspen_sapling"}, | 			"default:aspen_sapling"}, | ||||||
| 	action = function(pos) | 	action = function(pos) | ||||||
| 		minetest.get_node_timer(pos):start(math.random(1200, 2400)) | 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -468,7 +468,9 @@ function default.sapling_on_place(itemstack, placer, pointed_thing, | |||||||
| 	local node = minetest.get_node_or_nil(pos) | 	local node = minetest.get_node_or_nil(pos) | ||||||
| 	local pdef = node and minetest.registered_nodes[node.name] | 	local pdef = node and minetest.registered_nodes[node.name] | ||||||
|  |  | ||||||
| 	if pdef and pdef.on_rightclick and not placer:get_player_control().sneak then | 	if pdef and pdef.on_rightclick and | ||||||
|  | 			not (placer and placer:is_player() and | ||||||
|  | 			placer:get_player_control().sneak) then | ||||||
| 		return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing) | 		return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -481,7 +483,7 @@ function default.sapling_on_place(itemstack, placer, pointed_thing, | |||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	local player_name = placer:get_player_name() | 	local player_name = placer and placer:get_player_name() or "" | ||||||
| 	-- Check sapling position for protection | 	-- Check sapling position for protection | ||||||
| 	if minetest.is_protected(pos, player_name) then | 	if minetest.is_protected(pos, player_name) then | ||||||
| 		minetest.record_protection_violation(pos, player_name) | 		minetest.record_protection_violation(pos, player_name) | ||||||
|   | |||||||
| @@ -203,12 +203,7 @@ end | |||||||
|  |  | ||||||
| local function can_dig_door(pos, digger) | local function can_dig_door(pos, digger) | ||||||
| 	replace_old_owner_information(pos) | 	replace_old_owner_information(pos) | ||||||
| 	if default.can_interact_with_node(digger, pos) then | 	return default.can_interact_with_node(digger, pos) | ||||||
| 		return true |  | ||||||
| 	else |  | ||||||
| 		minetest.record_protection_violation(pos, digger:get_player_name()) |  | ||||||
| 		return false |  | ||||||
| 	end |  | ||||||
| end | end | ||||||
|  |  | ||||||
| function doors.register(name, def) | function doors.register(name, def) | ||||||
| @@ -266,7 +261,8 @@ function doors.register(name, def) | |||||||
| 			local node = minetest.get_node(pointed_thing.under) | 			local node = minetest.get_node(pointed_thing.under) | ||||||
| 			local pdef = minetest.registered_nodes[node.name] | 			local pdef = minetest.registered_nodes[node.name] | ||||||
| 			if pdef and pdef.on_rightclick and | 			if pdef and pdef.on_rightclick and | ||||||
| 					not placer:get_player_control().sneak then | 					not (placer and placer:is_player() and | ||||||
|  | 					placer:get_player_control().sneak) then | ||||||
| 				return pdef.on_rightclick(pointed_thing.under, | 				return pdef.on_rightclick(pointed_thing.under, | ||||||
| 						node, placer, itemstack, pointed_thing) | 						node, placer, itemstack, pointed_thing) | ||||||
| 			end | 			end | ||||||
| @@ -290,12 +286,12 @@ function doors.register(name, def) | |||||||
| 				return itemstack | 				return itemstack | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			local pn = placer:get_player_name() | 			local pn = placer and placer:get_player_name() or "" | ||||||
| 			if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then | 			if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then | ||||||
| 				return itemstack | 				return itemstack | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			local dir = minetest.dir_to_facedir(placer:get_look_dir()) | 			local dir = placer and minetest.dir_to_facedir(placer:get_look_dir()) or 0 | ||||||
|  |  | ||||||
| 			local ref = { | 			local ref = { | ||||||
| 				{x = -1, y = 0, z = 0}, | 				{x = -1, y = 0, z = 0}, | ||||||
| @@ -712,7 +708,7 @@ function doors.register_fencegate(name, def) | |||||||
| 	local fence = { | 	local fence = { | ||||||
| 		description = def.description, | 		description = def.description, | ||||||
| 		drawtype = "mesh", | 		drawtype = "mesh", | ||||||
| 		tiles = {def.texture}, | 		tiles = {}, | ||||||
| 		paramtype = "light", | 		paramtype = "light", | ||||||
| 		paramtype2 = "facedir", | 		paramtype2 = "facedir", | ||||||
| 		sunlight_propagates = true, | 		sunlight_propagates = true, | ||||||
| @@ -734,6 +730,16 @@ function doors.register_fencegate(name, def) | |||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	if type(def.texture) == "string" then | ||||||
|  | 		fence.tiles[1] = {name = def.texture, backface_culling = true} | ||||||
|  | 	elseif def.texture.backface_culling == nil then | ||||||
|  | 		fence.tiles[1] = table.copy(def.texture) | ||||||
|  | 		fence.tiles[1].backface_culling = true | ||||||
|  | 	else | ||||||
|  | 		fence.tiles[1] = def.texture | ||||||
|  | 	end | ||||||
|  |  | ||||||
| 	if not fence.sounds then | 	if not fence.sounds then | ||||||
| 		fence.sounds = default.node_sound_wood_defaults() | 		fence.sounds = default.node_sound_wood_defaults() | ||||||
| 	end | 	end | ||||||
|   | |||||||
| @@ -118,15 +118,6 @@ farming.register_hoe = function(name, def) | |||||||
| 				{"", "group:stick", ""} | 				{"", "group:stick", ""} | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| 		-- Reverse Recipe |  | ||||||
| 		minetest.register_craft({ |  | ||||||
| 			output = name:sub(2), |  | ||||||
| 			recipe = { |  | ||||||
| 				{"", def.material, def.material}, |  | ||||||
| 				{"", "group:stick", ""}, |  | ||||||
| 				{"", "group:stick", ""} |  | ||||||
| 			} |  | ||||||
| 		}) |  | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -153,12 +144,14 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname) | |||||||
| 	local under = minetest.get_node(pt.under) | 	local under = minetest.get_node(pt.under) | ||||||
| 	local above = minetest.get_node(pt.above) | 	local above = minetest.get_node(pt.above) | ||||||
|  |  | ||||||
| 	if minetest.is_protected(pt.under, placer:get_player_name()) then | 	local player_name = placer and placer:get_player_name() or "" | ||||||
| 		minetest.record_protection_violation(pt.under, placer:get_player_name()) |  | ||||||
|  | 	if minetest.is_protected(pt.under, player_name) then | ||||||
|  | 		minetest.record_protection_violation(pt.under, player_name) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	if minetest.is_protected(pt.above, placer:get_player_name()) then | 	if minetest.is_protected(pt.above, player_name) then | ||||||
| 		minetest.record_protection_violation(pt.above, placer:get_player_name()) | 		minetest.record_protection_violation(pt.above, player_name) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -189,7 +182,7 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname) | |||||||
| 	minetest.add_node(pt.above, {name = plantname, param2 = 1}) | 	minetest.add_node(pt.above, {name = plantname, param2 = 1}) | ||||||
| 	tick(pt.above) | 	tick(pt.above) | ||||||
| 	if not (creative and creative.is_enabled_for | 	if not (creative and creative.is_enabled_for | ||||||
| 			and creative.is_enabled_for(placer:get_player_name())) then | 			and creative.is_enabled_for(player_name)) then | ||||||
| 		itemstack:take_item() | 		itemstack:take_item() | ||||||
| 	end | 	end | ||||||
| 	return itemstack | 	return itemstack | ||||||
| @@ -319,7 +312,8 @@ farming.register_plant = function(name, def) | |||||||
| 			local node = minetest.get_node(under) | 			local node = minetest.get_node(under) | ||||||
| 			local udef = minetest.registered_nodes[node.name] | 			local udef = minetest.registered_nodes[node.name] | ||||||
| 			if udef and udef.on_rightclick and | 			if udef and udef.on_rightclick and | ||||||
| 					not (placer and placer:get_player_control().sneak) then | 					not (placer and placer:is_player() and | ||||||
|  | 					placer:get_player_control().sneak) then | ||||||
| 				return udef.on_rightclick(under, node, placer, itemstack, | 				return udef.on_rightclick(under, node, placer, itemstack, | ||||||
| 					pointed_thing) or itemstack | 					pointed_thing) or itemstack | ||||||
| 			end | 			end | ||||||
|   | |||||||
| @@ -1,2 +1,3 @@ | |||||||
| default | default | ||||||
| wool | wool | ||||||
|  | stairs | ||||||
|   | |||||||
| @@ -98,6 +98,16 @@ minetest.register_node("farming:straw", { | |||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | stairs.register_stair_and_slab( | ||||||
|  | 	"straw", | ||||||
|  | 	"farming:straw", | ||||||
|  | 	{snappy = 3, flammable = 4}, | ||||||
|  | 	{"farming_straw.png"}, | ||||||
|  | 	"Straw Stair", | ||||||
|  | 	"Straw Slab", | ||||||
|  | 	default.node_sound_leaves_defaults() | ||||||
|  | ) | ||||||
|  |  | ||||||
| minetest.register_abm({ | minetest.register_abm({ | ||||||
| 	label = "Farming soil", | 	label = "Farming soil", | ||||||
| 	nodenames = {"group:field"}, | 	nodenames = {"group:field"}, | ||||||
|   | |||||||
| @@ -127,24 +127,29 @@ function flowers.flower_spread(pos, node) | |||||||
|  |  | ||||||
| 	local pos0 = vector.subtract(pos, 4) | 	local pos0 = vector.subtract(pos, 4) | ||||||
| 	local pos1 = vector.add(pos, 4) | 	local pos1 = vector.add(pos, 4) | ||||||
| 	if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 3 then | 	-- Maximum flower density created by mapgen is 13 per 9x9 area. | ||||||
|  | 	-- The limit of 7 below was tuned by in-game testing to result in a maximum | ||||||
|  | 	-- flower density by ABM spread of 13 per 9x9 area. | ||||||
|  | 	-- Warning: Setting this limit theoretically without in-game testing | ||||||
|  | 	-- results in a maximum flower density by ABM spread that is far too high. | ||||||
|  | 	if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 7 then | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	local soils = minetest.find_nodes_in_area_under_air( | 	local soils = minetest.find_nodes_in_area_under_air( | ||||||
| 		pos0, pos1, "group:soil") | 		pos0, pos1, "group:soil") | ||||||
| 	if #soils > 0 then | 	local num_soils = #soils | ||||||
| 		local seedling = soils[math.random(#soils)] | 	if num_soils >= 1 then | ||||||
| 		local seedling_above = | 		for si = 1, math.min(3, num_soils) do | ||||||
| 			{x = seedling.x, y = seedling.y + 1, z = seedling.z} | 			local soil = soils[math.random(num_soils)] | ||||||
| 		light = minetest.get_node_light(seedling_above) | 			local soil_above = {x = soil.x, y = soil.y + 1, z = soil.z} | ||||||
| 		if not light or light < 13 or | 			light = minetest.get_node_light(soil_above) | ||||||
|  | 			if light and light >= 13 and | ||||||
| 					-- Desert sand is in the soil group | 					-- Desert sand is in the soil group | ||||||
| 				minetest.get_node(seedling).name == "default:desert_sand" then | 					minetest.get_node(soil).name ~= "default:desert_sand" then | ||||||
| 			return | 				minetest.set_node(soil_above, {name = node.name}) | ||||||
|  | 			end | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		minetest.set_node(seedling_above, {name = node.name}) |  | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -152,7 +157,7 @@ minetest.register_abm({ | |||||||
| 	label = "Flower spread", | 	label = "Flower spread", | ||||||
| 	nodenames = {"group:flora"}, | 	nodenames = {"group:flora"}, | ||||||
| 	interval = 13, | 	interval = 13, | ||||||
| 	chance = 96, | 	chance = 300, | ||||||
| 	action = function(...) | 	action = function(...) | ||||||
| 		flowers.flower_spread(...) | 		flowers.flower_spread(...) | ||||||
| 	end, | 	end, | ||||||
| @@ -204,38 +209,34 @@ minetest.register_node("flowers:mushroom_brown", { | |||||||
|  |  | ||||||
| -- Mushroom spread and death | -- Mushroom spread and death | ||||||
|  |  | ||||||
| minetest.register_abm({ | function flowers.mushroom_spread(pos, node) | ||||||
| 	label = "Mushroom spread", |  | ||||||
| 	nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, |  | ||||||
| 	interval = 11, |  | ||||||
| 	chance = 50, |  | ||||||
| 	action = function(pos, node) |  | ||||||
| 	if minetest.get_node_light(pos, nil) == 15 then | 	if minetest.get_node_light(pos, nil) == 15 then | ||||||
| 		minetest.remove_node(pos) | 		minetest.remove_node(pos) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 		local random = { | 	local positions = minetest.find_nodes_in_area_under_air( | ||||||
| 			x = pos.x + math.random(-2, 2), | 		{x = pos.x - 1, y = pos.y - 2, z = pos.z - 1}, | ||||||
| 			y = pos.y + math.random(-1, 1), | 		{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, | ||||||
| 			z = pos.z + math.random(-2, 2) | 		{"group:soil", "group:tree"}) | ||||||
| 		} | 	if #positions == 0 then | ||||||
| 		local random_node = minetest.get_node_or_nil(random) |  | ||||||
| 		if not random_node or random_node.name ~= "air" then |  | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 		local node_under = minetest.get_node_or_nil({x = random.x, | 	local pos2 = positions[math.random(#positions)] | ||||||
| 			y = random.y - 1, z = random.z}) | 	pos2.y = pos2.y + 1 | ||||||
| 		if not node_under then | 	if minetest.get_node_light(pos, 0.5) <= 3 and | ||||||
| 			return | 			minetest.get_node_light(pos2, 0.5) <= 3 then | ||||||
|  | 		minetest.set_node(pos2, {name = node.name}) | ||||||
|  | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| 		if (minetest.get_item_group(node_under.name, "soil") ~= 0 or | minetest.register_abm({ | ||||||
| 				minetest.get_item_group(node_under.name, "tree") ~= 0) and | 	label = "Mushroom spread", | ||||||
| 				minetest.get_node_light(pos, 0.5) <= 3 and | 	nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, | ||||||
| 				minetest.get_node_light(random, 0.5) <= 3 then | 	interval = 11, | ||||||
| 			minetest.set_node(random, {name = node.name}) | 	chance = 150, | ||||||
| 		end | 	action = function(...) | ||||||
| 	end | 		flowers.mushroom_spread(...) | ||||||
|  | 	end, | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -280,12 +281,17 @@ minetest.register_node("flowers:waterlily", { | |||||||
|  |  | ||||||
| 	on_place = function(itemstack, placer, pointed_thing) | 	on_place = function(itemstack, placer, pointed_thing) | ||||||
| 		local pos = pointed_thing.above | 		local pos = pointed_thing.above | ||||||
| 		local node = minetest.get_node(pointed_thing.under).name | 		local node = minetest.get_node(pointed_thing.under) | ||||||
| 		local def = minetest.registered_nodes[node] | 		local def = minetest.registered_nodes[node.name] | ||||||
| 		local player_name = placer:get_player_name() | 		local player_name = placer and placer:get_player_name() or "" | ||||||
|  |  | ||||||
|  | 		if def and def.on_rightclick then | ||||||
|  | 			return def.on_rightclick(pointed_thing.under, node, placer, itemstack, | ||||||
|  | 					pointed_thing) | ||||||
|  | 		end | ||||||
|  |  | ||||||
| 		if def and def.liquidtype == "source" and | 		if def and def.liquidtype == "source" and | ||||||
| 				minetest.get_item_group(node, "water") > 0 then | 				minetest.get_item_group(node.name, "water") > 0 then | ||||||
| 			if not minetest.is_protected(pos, player_name) then | 			if not minetest.is_protected(pos, player_name) then | ||||||
| 				minetest.set_node(pos, {name = "flowers:waterlily", | 				minetest.set_node(pos, {name = "flowers:waterlily", | ||||||
| 					param2 = math.random(0, 3)}) | 					param2 = math.random(0, 3)}) | ||||||
|   | |||||||
| @@ -85,9 +85,10 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) | |||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	local pos = pointed_thing.under | 	local pos = pointed_thing.under | ||||||
|  | 	local player_name = user and user:get_player_name() or "" | ||||||
|  |  | ||||||
| 	if minetest.is_protected(pos, user:get_player_name()) then | 	if minetest.is_protected(pos, player_name) then | ||||||
| 		minetest.record_protection_violation(pos, user:get_player_name()) | 		minetest.record_protection_violation(pos, player_name) | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -133,8 +134,8 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) | |||||||
| 		minetest.check_for_falling(pos) | 		minetest.check_for_falling(pos) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if not (creative and creative.is_enabled_for | 	if not (creative and creative.is_enabled_for and | ||||||
| 			and creative.is_enabled_for(user:get_player_name())) then | 			creative.is_enabled_for(player_name)) then | ||||||
| 		itemstack:add_wear(65535 / ((uses or 200) - 1)) | 		itemstack:add_wear(65535 / ((uses or 200) - 1)) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,7 +29,8 @@ end | |||||||
| function sfinv.get_nav_fs(player, context, nav, current_idx) | function sfinv.get_nav_fs(player, context, nav, current_idx) | ||||||
| 	-- Only show tabs if there is more than one page | 	-- Only show tabs if there is more than one page | ||||||
| 	if #nav > 1 then | 	if #nav > 1 then | ||||||
| 		return "tabheader[0,0;tabs;" .. table.concat(nav, ",") .. ";" .. current_idx .. ";true;false]" | 		return "tabheader[0,0;sfinv_nav_tabs;" .. table.concat(nav, ",") .. | ||||||
|  | 				";" .. current_idx .. ";true;false]" | ||||||
| 	else | 	else | ||||||
| 		return "" | 		return "" | ||||||
| 	end | 	end | ||||||
| @@ -84,9 +85,20 @@ function sfinv.get_formspec(player, context) | |||||||
| 		return page:get(player, context) | 		return page:get(player, context) | ||||||
| 	else | 	else | ||||||
| 		local old_page = context.page | 		local old_page = context.page | ||||||
| 		context.page = sfinv.get_homepage_name(player) | 		local home_page = sfinv.get_homepage_name(player) | ||||||
|  |  | ||||||
|  | 		if old_page == home_page then | ||||||
|  | 			minetest.log("error", "[sfinv] Couldn't find " .. dump(old_page) .. | ||||||
|  | 					", which is also the old page") | ||||||
|  |  | ||||||
|  | 			return "" | ||||||
|  | 		end | ||||||
|  |  | ||||||
|  | 		context.page = home_page | ||||||
| 		assert(sfinv.pages[context.page], "[sfinv] Invalid homepage") | 		assert(sfinv.pages[context.page], "[sfinv] Invalid homepage") | ||||||
| 		minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) .. " so using switching to homepage") | 		minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) .. | ||||||
|  | 				" so switching to homepage") | ||||||
|  |  | ||||||
| 		return sfinv.get_formspec(player, context) | 		return sfinv.get_formspec(player, context) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
| @@ -151,8 +163,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) | |||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- Was a tab selected? | 	-- Was a tab selected? | ||||||
| 	if fields.tabs and context.nav then | 	if fields.sfinv_nav_tabs and context.nav then | ||||||
| 		local tid = tonumber(fields.tabs) | 		local tid = tonumber(fields.sfinv_nav_tabs) | ||||||
| 		if tid and tid > 0 then | 		if tid and tid > 0 then | ||||||
| 			local id = context.nav[tid] | 			local id = context.nav[tid] | ||||||
| 			local page = sfinv.pages[id] | 			local page = sfinv.pages[id] | ||||||
|   | |||||||
| @@ -1,2 +1 @@ | |||||||
| default | default | ||||||
| farming |  | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ local function rotate_and_place(itemstack, placer, pointed_thing) | |||||||
| 	local p1 = pointed_thing.above | 	local p1 = pointed_thing.above | ||||||
| 	local param2 = 0 | 	local param2 = 0 | ||||||
|  |  | ||||||
|  | 	if placer then | ||||||
| 		local placer_pos = placer:getpos() | 		local placer_pos = placer:getpos() | ||||||
| 		if placer_pos then | 		if placer_pos then | ||||||
| 			param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) | 			param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) | ||||||
| @@ -39,6 +40,7 @@ local function rotate_and_place(itemstack, placer, pointed_thing) | |||||||
| 				param2 = 21 | 				param2 = 21 | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
|  | 	end | ||||||
| 	return minetest.item_place(itemstack, placer, pointed_thing, param2) | 	return minetest.item_place(itemstack, placer, pointed_thing, param2) | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -46,16 +48,29 @@ end | |||||||
| -- Node will be called stairs:stair_<subname> | -- Node will be called stairs:stair_<subname> | ||||||
|  |  | ||||||
| function stairs.register_stair(subname, recipeitem, groups, images, description, sounds) | function stairs.register_stair(subname, recipeitem, groups, images, description, sounds) | ||||||
| 	groups.stair = 1 | 	local stair_images = {} | ||||||
|  | 	for i, image in ipairs(images) do | ||||||
|  | 		if type(image) == "string" then | ||||||
|  | 			stair_images[i] = { | ||||||
|  | 				name = image, | ||||||
|  | 				backface_culling = true, | ||||||
|  | 			} | ||||||
|  | 		elseif image.backface_culling == nil then -- override using any other value | ||||||
|  | 			stair_images[i] = table.copy(image) | ||||||
|  | 			stair_images[i].backface_culling = true | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 	local new_groups = table.copy(groups) | ||||||
|  | 	new_groups.stair = 1 | ||||||
| 	minetest.register_node(":stairs:stair_" .. subname, { | 	minetest.register_node(":stairs:stair_" .. subname, { | ||||||
| 		description = description, | 		description = description, | ||||||
| 		drawtype = "mesh", | 		drawtype = "mesh", | ||||||
| 		mesh = "stairs_stair.obj", | 		mesh = "stairs_stair.obj", | ||||||
| 		tiles = images, | 		tiles = stair_images, | ||||||
| 		paramtype = "light", | 		paramtype = "light", | ||||||
| 		paramtype2 = "facedir", | 		paramtype2 = "facedir", | ||||||
| 		is_ground_content = false, | 		is_ground_content = false, | ||||||
| 		groups = groups, | 		groups = new_groups, | ||||||
| 		sounds = sounds, | 		sounds = sounds, | ||||||
| 		selection_box = { | 		selection_box = { | ||||||
| 			type = "fixed", | 			type = "fixed", | ||||||
| @@ -89,16 +104,7 @@ function stairs.register_stair(subname, recipeitem, groups, images, description, | |||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if recipeitem then | 	if recipeitem then | ||||||
| 		minetest.register_craft({ | 		-- Recipe matches appearence in inventory | ||||||
| 			output = 'stairs:stair_' .. subname .. ' 8', |  | ||||||
| 			recipe = { |  | ||||||
| 				{recipeitem, "", ""}, |  | ||||||
| 				{recipeitem, recipeitem, ""}, |  | ||||||
| 				{recipeitem, recipeitem, recipeitem}, |  | ||||||
| 			}, |  | ||||||
| 		}) |  | ||||||
|  |  | ||||||
| 		-- Flipped recipe for the silly minecrafters |  | ||||||
| 		minetest.register_craft({ | 		minetest.register_craft({ | ||||||
| 			output = 'stairs:stair_' .. subname .. ' 8', | 			output = 'stairs:stair_' .. subname .. ' 8', | ||||||
| 			recipe = { | 			recipe = { | ||||||
| @@ -132,7 +138,8 @@ local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4} | |||||||
| -- Node will be called stairs:slab_<subname> | -- Node will be called stairs:slab_<subname> | ||||||
|  |  | ||||||
| function stairs.register_slab(subname, recipeitem, groups, images, description, sounds) | function stairs.register_slab(subname, recipeitem, groups, images, description, sounds) | ||||||
| 	groups.slab = 1 | 	local new_groups = table.copy(groups) | ||||||
|  | 	new_groups.slab = 1 | ||||||
| 	minetest.register_node(":stairs:slab_" .. subname, { | 	minetest.register_node(":stairs:slab_" .. subname, { | ||||||
| 		description = description, | 		description = description, | ||||||
| 		drawtype = "nodebox", | 		drawtype = "nodebox", | ||||||
| @@ -140,7 +147,7 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, | |||||||
| 		paramtype = "light", | 		paramtype = "light", | ||||||
| 		paramtype2 = "facedir", | 		paramtype2 = "facedir", | ||||||
| 		is_ground_content = false, | 		is_ground_content = false, | ||||||
| 		groups = groups, | 		groups = new_groups, | ||||||
| 		sounds = sounds, | 		sounds = sounds, | ||||||
| 		node_box = { | 		node_box = { | ||||||
| 			type = "fixed", | 			type = "fixed", | ||||||
| @@ -149,8 +156,9 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, | |||||||
| 		on_place = function(itemstack, placer, pointed_thing) | 		on_place = function(itemstack, placer, pointed_thing) | ||||||
| 			local under = minetest.get_node(pointed_thing.under) | 			local under = minetest.get_node(pointed_thing.under) | ||||||
| 			local wield_item = itemstack:get_name() | 			local wield_item = itemstack:get_name() | ||||||
|  | 			local player_name = placer and placer:get_player_name() or "" | ||||||
| 			local creative_enabled = (creative and creative.is_enabled_for | 			local creative_enabled = (creative and creative.is_enabled_for | ||||||
| 					and creative.is_enabled_for(placer:get_player_name())) | 					and creative.is_enabled_for(player_name)) | ||||||
|  |  | ||||||
| 			if under and under.name:find("stairs:slab_") then | 			if under and under.name:find("stairs:slab_") then | ||||||
| 				-- place slab using under node orientation | 				-- place slab using under node orientation | ||||||
| @@ -166,9 +174,8 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, | |||||||
| 					if not recipeitem then | 					if not recipeitem then | ||||||
| 						return itemstack | 						return itemstack | ||||||
| 					end | 					end | ||||||
| 					local player_name = placer:get_player_name() |  | ||||||
| 					if minetest.is_protected(pointed_thing.under, player_name) and not | 					if minetest.is_protected(pointed_thing.under, player_name) and not | ||||||
| 							minetest.check_player_privs(placer, "protection_bypass") then | 							minetest.check_player_privs(player_name, "protection_bypass") then | ||||||
| 						minetest.record_protection_violation(pointed_thing.under, | 						minetest.record_protection_violation(pointed_thing.under, | ||||||
| 							player_name) | 							player_name) | ||||||
| 						return | 						return | ||||||
| @@ -538,16 +545,6 @@ stairs.register_stair_and_slab( | |||||||
| 	default.node_sound_stone_defaults() | 	default.node_sound_stone_defaults() | ||||||
| ) | ) | ||||||
|  |  | ||||||
| stairs.register_stair_and_slab( |  | ||||||
| 	"straw", |  | ||||||
| 	"farming:straw", |  | ||||||
| 	{snappy = 3, flammable = 4}, |  | ||||||
| 	{"farming_straw.png"}, |  | ||||||
| 	"Straw Stair", |  | ||||||
| 	"Straw Slab", |  | ||||||
| 	default.node_sound_leaves_defaults() |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| stairs.register_stair_and_slab( | stairs.register_stair_and_slab( | ||||||
| 	"steelblock", | 	"steelblock", | ||||||
| 	"default:steelblock", | 	"default:steelblock", | ||||||
|   | |||||||
| @@ -86,8 +86,8 @@ end | |||||||
| local basic_flame_on_construct -- cached value | local basic_flame_on_construct -- cached value | ||||||
| local function destroy(drops, npos, cid, c_air, c_fire, | local function destroy(drops, npos, cid, c_air, c_fire, | ||||||
| 		on_blast_queue, on_construct_queue, | 		on_blast_queue, on_construct_queue, | ||||||
| 		ignore_protection, ignore_on_blast) | 		ignore_protection, ignore_on_blast, owner) | ||||||
| 	if not ignore_protection and minetest.is_protected(npos, "") then | 	if not ignore_protection and minetest.is_protected(npos, owner) then | ||||||
| 		return cid | 		return cid | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -208,6 +208,7 @@ local function add_effects(pos, radius, drops) | |||||||
| 		collisiondetection = false, | 		collisiondetection = false, | ||||||
| 		vertical = false, | 		vertical = false, | ||||||
| 		texture = "tnt_boom.png", | 		texture = "tnt_boom.png", | ||||||
|  | 		glow = 15, | ||||||
| 	}) | 	}) | ||||||
| 	minetest.add_particlespawner({ | 	minetest.add_particlespawner({ | ||||||
| 		amount = 64, | 		amount = 64, | ||||||
| @@ -266,13 +267,13 @@ function tnt.burn(pos, nodename) | |||||||
| 	elseif def.on_ignite then | 	elseif def.on_ignite then | ||||||
| 		def.on_ignite(pos) | 		def.on_ignite(pos) | ||||||
| 	elseif minetest.get_item_group(name, "tnt") > 0 then | 	elseif minetest.get_item_group(name, "tnt") > 0 then | ||||||
|  | 		minetest.swap_node(pos, {name = name .. "_burning"}) | ||||||
| 		minetest.sound_play("tnt_ignite", {pos = pos}) | 		minetest.sound_play("tnt_ignite", {pos = pos}) | ||||||
| 		minetest.set_node(pos, {name = name .. "_burning"}) |  | ||||||
| 		minetest.get_node_timer(pos):start(1) | 		minetest.get_node_timer(pos):start(1) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) | local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast, owner, explode_center) | ||||||
| 	pos = vector.round(pos) | 	pos = vector.round(pos) | ||||||
| 	-- scan for adjacent TNT nodes first, and enlarge the explosion | 	-- scan for adjacent TNT nodes first, and enlarge the explosion | ||||||
| 	local vm1 = VoxelManip() | 	local vm1 = VoxelManip() | ||||||
| @@ -286,6 +287,10 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) | |||||||
| 	local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning") | 	local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning") | ||||||
| 	local c_tnt_boom = minetest.get_content_id("tnt:boom") | 	local c_tnt_boom = minetest.get_content_id("tnt:boom") | ||||||
| 	local c_air = minetest.get_content_id("air") | 	local c_air = minetest.get_content_id("air") | ||||||
|  | 	-- make sure we still have explosion even when centre node isnt tnt related | ||||||
|  | 	if explode_center then | ||||||
|  | 		count = 1 | ||||||
|  | 	end | ||||||
|  |  | ||||||
| 	for z = pos.z - 2, pos.z + 2 do | 	for z = pos.z - 2, pos.z + 2 do | ||||||
| 	for y = pos.y - 2, pos.y + 2 do | 	for y = pos.y - 2, pos.y + 2 do | ||||||
| @@ -333,7 +338,7 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) | |||||||
| 			if cid ~= c_air then | 			if cid ~= c_air then | ||||||
| 				data[vi] = destroy(drops, p, cid, c_air, c_fire, | 				data[vi] = destroy(drops, p, cid, c_air, c_fire, | ||||||
| 					on_blast_queue, on_construct_queue, | 					on_blast_queue, on_construct_queue, | ||||||
| 					ignore_protection, ignore_on_blast) | 					ignore_protection, ignore_on_blast, owner) | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 		vi = vi + 1 | 		vi = vi + 1 | ||||||
| @@ -375,16 +380,26 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) | |||||||
| 		queued_data.fn(queued_data.pos) | 		queued_data.fn(queued_data.pos) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|  | 	minetest.log("action", "TNT owned by " .. owner .. " detonated at " .. | ||||||
|  | 		minetest.pos_to_string(pos) .. " with radius " .. radius) | ||||||
|  |  | ||||||
| 	return drops, radius | 	return drops, radius | ||||||
| end | end | ||||||
|  |  | ||||||
| function tnt.boom(pos, def) | function tnt.boom(pos, def) | ||||||
| 	minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 2*64}) | 	def = def or {} | ||||||
|  | 	def.radius = def.radius or 1 | ||||||
|  | 	def.damage_radius = def.damage_radius or def.radius * 2 | ||||||
|  | 	local meta = minetest.get_meta(pos) | ||||||
|  | 	local owner = meta:get_string("owner") | ||||||
|  | 	if not def.explode_center then | ||||||
| 		minetest.set_node(pos, {name = "tnt:boom"}) | 		minetest.set_node(pos, {name = "tnt:boom"}) | ||||||
|  | 	end | ||||||
|  | 	minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 2*64}) | ||||||
| 	local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection, | 	local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection, | ||||||
| 			def.ignore_on_blast) | 			def.ignore_on_blast, owner, def.explode_center) | ||||||
| 	-- append entity drops | 	-- append entity drops | ||||||
| 	local damage_radius = (radius / def.radius) * def.damage_radius | 	local damage_radius = (radius / math.max(1, def.radius)) * def.damage_radius | ||||||
| 	entity_physics(pos, damage_radius, drops) | 	entity_physics(pos, damage_radius, drops) | ||||||
| 	if not def.disable_drops then | 	if not def.disable_drops then | ||||||
| 		eject_drops(drops, pos, radius) | 		eject_drops(drops, pos, radius) | ||||||
| @@ -400,12 +415,6 @@ minetest.register_node("tnt:boom", { | |||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	drop = "", | 	drop = "", | ||||||
| 	groups = {dig_immediate = 3}, | 	groups = {dig_immediate = 3}, | ||||||
| 	on_construct = function(pos) |  | ||||||
| 		minetest.get_node_timer(pos):start(0.4) |  | ||||||
| 	end, |  | ||||||
| 	on_timer = function(pos, elapsed) |  | ||||||
| 		minetest.remove_node(pos) |  | ||||||
| 	end, |  | ||||||
| 	-- unaffected by explosions | 	-- unaffected by explosions | ||||||
| 	on_blast = function() end, | 	on_blast = function() end, | ||||||
| }) | }) | ||||||
| @@ -508,8 +517,8 @@ minetest.register_node("tnt:gunpowder_burning", { | |||||||
| 	on_timer = function(pos, elapsed) | 	on_timer = function(pos, elapsed) | ||||||
| 		for dx = -1, 1 do | 		for dx = -1, 1 do | ||||||
| 		for dz = -1, 1 do | 		for dz = -1, 1 do | ||||||
|  | 			if math.abs(dx) + math.abs(dz) == 1 then | ||||||
| 				for dy = -1, 1 do | 				for dy = -1, 1 do | ||||||
| 			if not (dx == 0 and dz == 0) then |  | ||||||
| 					tnt.burn({ | 					tnt.burn({ | ||||||
| 						x = pos.x + dx, | 						x = pos.x + dx, | ||||||
| 						y = pos.y + dy, | 						y = pos.y + dy, | ||||||
| @@ -579,9 +588,16 @@ function tnt.register_tnt(def) | |||||||
| 			is_ground_content = false, | 			is_ground_content = false, | ||||||
| 			groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5}, | 			groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5}, | ||||||
| 			sounds = default.node_sound_wood_defaults(), | 			sounds = default.node_sound_wood_defaults(), | ||||||
|  | 			after_place_node = function(pos, placer) | ||||||
|  | 				if placer:is_player() then | ||||||
|  | 					local meta = minetest.get_meta(pos) | ||||||
|  | 					meta:set_string("owner", placer:get_player_name()) | ||||||
|  | 				end | ||||||
|  | 			end, | ||||||
| 			on_punch = function(pos, node, puncher) | 			on_punch = function(pos, node, puncher) | ||||||
| 				if puncher:get_wielded_item():get_name() == "default:torch" then | 				if puncher:get_wielded_item():get_name() == "default:torch" then | ||||||
| 					minetest.set_node(pos, {name = name .. "_burning"}) | 					minetest.swap_node(pos, {name = name .. "_burning"}) | ||||||
|  | 					minetest.registered_nodes[name .. "_burning"].on_construct(pos) | ||||||
| 					minetest.log("action", puncher:get_player_name() .. | 					minetest.log("action", puncher:get_player_name() .. | ||||||
| 						" ignites " .. node.name .. " at " .. | 						" ignites " .. node.name .. " at " .. | ||||||
| 						minetest.pos_to_string(pos)) | 						minetest.pos_to_string(pos)) | ||||||
| @@ -600,10 +616,12 @@ function tnt.register_tnt(def) | |||||||
| 				} | 				} | ||||||
| 			}, | 			}, | ||||||
| 			on_burn = function(pos) | 			on_burn = function(pos) | ||||||
| 				minetest.set_node(pos, {name = name .. "_burning"}) | 				minetest.swap_node(pos, {name = name .. "_burning"}) | ||||||
|  | 				minetest.registered_nodes[name .. "_burning"].on_construct(pos) | ||||||
| 			end, | 			end, | ||||||
| 			on_ignite = function(pos, igniter) | 			on_ignite = function(pos, igniter) | ||||||
| 				minetest.set_node(pos, {name = name .. "_burning"}) | 				minetest.swap_node(pos, {name = name .. "_burning"}) | ||||||
|  | 				minetest.registered_nodes[name .. "_burning"].on_construct(pos) | ||||||
| 			end, | 			end, | ||||||
| 		}) | 		}) | ||||||
| 	end | 	end | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user