mirror of
				https://github.com/luanti-org/minetest_game.git
				synced 2025-10-26 13:25:30 +01:00 
			
		
		
		
	Compare commits
	
		
			46 Commits
		
	
	
		
	
	| 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 | ||||
|  | ||||
| 	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", | ||||
| 	groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, | ||||
| 	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`. | ||||
|   * `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. | ||||
|  | ||||
| * `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])` | ||||
|  | ||||
|   | ||||
| @@ -49,21 +49,24 @@ function beds.register_bed(name, def) | ||||
| 			local node = minetest.get_node(under) | ||||
| 			local udef = minetest.registered_nodes[node.name] | ||||
| 			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, | ||||
| 					pointed_thing) or itemstack | ||||
| 			end | ||||
|  | ||||
| 			local pos | ||||
| 			if minetest.registered_items[minetest.get_node(under).name].buildable_to then | ||||
| 			if udef and udef.buildable_to then | ||||
| 				pos = under | ||||
| 			else | ||||
| 				pos = pointed_thing.above | ||||
| 			end | ||||
|  | ||||
| 			if minetest.is_protected(pos, placer:get_player_name()) and | ||||
| 					not minetest.check_player_privs(placer, "protection_bypass") then | ||||
| 				minetest.record_protection_violation(pos, placer:get_player_name()) | ||||
| 			local player_name = placer and placer:get_player_name() or "" | ||||
|  | ||||
| 			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 | ||||
| 			end | ||||
|  | ||||
| @@ -72,12 +75,13 @@ function beds.register_bed(name, def) | ||||
| 				return itemstack | ||||
| 			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)) | ||||
|  | ||||
| 			if minetest.is_protected(botpos, placer:get_player_name()) and | ||||
| 					not minetest.check_player_privs(placer, "protection_bypass") then | ||||
| 				minetest.record_protection_violation(botpos, placer:get_player_name()) | ||||
| 			if minetest.is_protected(botpos, player_name) and | ||||
| 					not minetest.check_player_privs(player_name, "protection_bypass") then | ||||
| 				minetest.record_protection_violation(botpos, player_name) | ||||
| 				return itemstack | ||||
| 			end | ||||
|  | ||||
| @@ -90,7 +94,7 @@ function beds.register_bed(name, def) | ||||
| 			minetest.set_node(botpos, {name = name .. "_top", param2 = dir}) | ||||
|  | ||||
| 			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() | ||||
| 			end | ||||
| 			return itemstack | ||||
|   | ||||
| @@ -230,7 +230,8 @@ minetest.register_craftitem("boats:boat", { | ||||
| 		local node = minetest.get_node(under) | ||||
| 		local udef = minetest.registered_nodes[node.name] | ||||
| 		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, | ||||
| 				pointed_thing) or itemstack | ||||
| 		end | ||||
| @@ -244,9 +245,12 @@ minetest.register_craftitem("boats:boat", { | ||||
| 		pointed_thing.under.y = pointed_thing.under.y + 0.5 | ||||
| 		boat = minetest.add_entity(pointed_thing.under, "boats:boat") | ||||
| 		if boat then | ||||
| 			boat:setyaw(placer:get_look_horizontal()) | ||||
| 			if not (creative and creative.is_enabled_for | ||||
| 					and creative.is_enabled_for(placer:get_player_name())) then | ||||
| 			if placer then | ||||
| 				boat:setyaw(placer:get_look_horizontal()) | ||||
| 			end | ||||
| 			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() | ||||
| 			end | ||||
| 		end | ||||
|   | ||||
| @@ -68,6 +68,12 @@ minetest.register_node("bones:bones", { | ||||
| 	on_metadata_inventory_take = function(pos, listname, index, stack, player) | ||||
| 		local meta = minetest.get_meta(pos) | ||||
| 		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) | ||||
| 		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 | ||||
| 				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( | ||||
| 						pointed_thing.under, | ||||
| 						node, user, | ||||
|   | ||||
| @@ -58,7 +58,8 @@ end | ||||
|  | ||||
| function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) | ||||
| 	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 | ||||
| 		self.railtype = minetest.get_item_group(node, "connect_to_raillike") | ||||
| 	end | ||||
| @@ -105,7 +106,6 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, | ||||
| 		return | ||||
| 	end | ||||
| 	-- Player punches cart to alter velocity | ||||
| 	local vel = self.object:getvelocity() | ||||
| 	if puncher:get_player_name() == self.driver then | ||||
| 		if math.abs(vel.x + vel.z) > carts.punch_speed_max then | ||||
| 			return | ||||
| @@ -367,7 +367,8 @@ minetest.register_craftitem("carts:cart", { | ||||
| 		local node = minetest.get_node(under) | ||||
| 		local udef = minetest.registered_nodes[node.name] | ||||
| 		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, | ||||
| 				pointed_thing) or itemstack | ||||
| 		end | ||||
|   | ||||
| @@ -159,23 +159,29 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) | ||||
| end | ||||
|  | ||||
| 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 pf_pos = vector.round(old_pos) | ||||
| 	local pf_dir = vector.new(old_dir) | ||||
|  | ||||
| 	for i = 1, 3 do | ||||
| 		if vector.equals(pf_pos, pos) then | ||||
| 			-- Success! Cart moved on correctly | ||||
| 			return true | ||||
| 		end | ||||
| 		pf_dir, pf_switch = carts:get_rail_direction( | ||||
| 			pf_pos, pf_dir, ctrl, pf_switch, railtype) | ||||
|  | ||||
| 		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 | ||||
| 			-- No way forwards | ||||
| 			return false | ||||
| 		end | ||||
|  | ||||
| 		pf_pos = vector.add(pf_pos, pf_dir) | ||||
|  | ||||
| 		if vector.equals(pf_pos, pos) then | ||||
| 			-- Success! Cart moved on correctly | ||||
| 			return true | ||||
| 		end | ||||
| 	end | ||||
| 	-- Cart not found | ||||
| 	return false | ||||
| @@ -211,7 +217,12 @@ end | ||||
|  | ||||
| function carts:get_rail_groups(additional_groups) | ||||
| 	-- 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 | ||||
| 		for k, v in pairs(additional_groups) do | ||||
| 			groups[k] = v | ||||
|   | ||||
| @@ -40,16 +40,16 @@ end | ||||
|  | ||||
| -- Unlimited node placement | ||||
| minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) | ||||
| 	return creative.is_enabled_for(placer:get_player_name()) | ||||
| 	if placer and placer:is_player() then | ||||
| 		return creative.is_enabled_for(placer:get_player_name()) | ||||
| 	end | ||||
| end) | ||||
|  | ||||
| -- Don't pick up if the item is already in the inventory | ||||
| local old_handle_node_drops = minetest.handle_node_drops | ||||
| function minetest.handle_node_drops(pos, drops, digger) | ||||
| 	if not digger or not digger:is_player() then | ||||
| 		return | ||||
| 	end | ||||
| 	if not creative.is_enabled_for(digger:get_player_name()) then | ||||
| 	if not digger or not digger:is_player() or | ||||
| 		not creative.is_enabled_for(digger:get_player_name()) then | ||||
| 		return old_handle_node_drops(pos, drops, digger) | ||||
| 	end | ||||
| 	local inv = digger:get_inventory() | ||||
|   | ||||
| @@ -1,4 +1,19 @@ | ||||
| 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) | ||||
| 	local player_name = player:get_player_name() | ||||
| @@ -10,22 +25,25 @@ function creative.init_creative_inventory(player) | ||||
|  | ||||
| 	minetest.create_detached_inventory("creative_" .. player_name, { | ||||
| 		allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2) | ||||
| 			if not to_list == "main" then | ||||
| 				return count | ||||
| 			else | ||||
| 			local name = player2 and player2:get_player_name() or "" | ||||
| 			if not creative.is_enabled_for(name) or | ||||
| 					to_list == "main" then | ||||
| 				return 0 | ||||
| 			end | ||||
| 			return count | ||||
| 		end, | ||||
| 		allow_put = function(inv, listname, index, stack, player2) | ||||
| 			return 0 | ||||
| 		end, | ||||
| 		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 | ||||
| 		end, | ||||
| 		on_move = function(inv, from_list, from_index, to_list, to_index, count, player2) | ||||
| 		end, | ||||
| 		on_put = function(inv, listname, index, stack, player2) | ||||
| 		end, | ||||
| 		on_take = function(inv, listname, index, stack, player2) | ||||
| 			if stack and stack:get_count() > 0 then | ||||
| 				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)) | ||||
| 	local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name}) | ||||
|  | ||||
| 	for name, def in pairs(tab_content) do | ||||
| 		if not (def.groups.not_in_creative_inventory == 1) and | ||||
| 				def.description and def.description ~= "" and | ||||
| 				(def.name:find(inv.filter, 1, true) or | ||||
| 					def.description:lower():find(inv.filter, 1, true)) then | ||||
| 	local items = inventory_cache[tab_content] or init_creative_cache(tab_content) | ||||
|  | ||||
| 	for name, def in pairs(items) do | ||||
| 		if def.name:find(inv.filter, 1, true) or | ||||
| 				def.description:lower():find(inv.filter, 1, true) then | ||||
| 			creative_list[#creative_list+1] = name | ||||
| 		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] | ||||
| 					tooltip[creative_search;Search] | ||||
| 					tooltip[creative_clear;Reset] | ||||
| 					tooltip[creative_prev;Previous page] | ||||
| 					tooltip[creative_next;Next page] | ||||
| 					listring[current_player;main] | ||||
| 					field_close_on_enter[creative_filter;false] | ||||
| 				]] .. | ||||
| @@ -158,10 +178,6 @@ function creative.register_tab(name, title, items) | ||||
| 	}) | ||||
| 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("nodes", "Nodes", minetest.registered_nodes) | ||||
| 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_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_bookshelf_slot.png -- Derived from a texture by Gambit (CC-BY-SA 3.0) | ||||
|  | ||||
| brunob.santos (CC BY-SA 4.0): | ||||
|   default_desert_cobble.png | ||||
| @@ -131,7 +132,6 @@ BlockMen (CC BY-SA 3.0): | ||||
|   default_gold_ingot.png | ||||
|   default_tool_steelsword.png | ||||
|   default_diamond.png | ||||
|   default_book.png | ||||
|   default_tool_*.png | ||||
|   default_lava_source_animated.png | ||||
|   default_lava_flowing_animated.png | ||||
| @@ -145,11 +145,7 @@ BlockMen (CC BY-SA 3.0): | ||||
|   bubble.png | ||||
|   gui_*.png | ||||
|  | ||||
| Wuzzy (CC BY-SA 3.0): | ||||
|   default_bookshelf_slot.png (based on default_book.png) | ||||
|  | ||||
| sofar (CC BY-SA 3.0): | ||||
|   default_book_written.png, based on default_book.png | ||||
|   default_aspen_sapling | ||||
|   default_aspen_tree | ||||
|   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_key.png | ||||
|   default_key_skeleton.png | ||||
|   default_book.png | ||||
|  | ||||
| asl97 (CC BY-SA 3.0): | ||||
|   default_ice.png | ||||
| @@ -221,6 +218,9 @@ kilbith (CC BY-SA 3.0): | ||||
|   default_tin_ingot.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): | ||||
|   1: http://www.freesound.org/people/cmusounddesign/sounds/71947/ | ||||
|   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({ | ||||
| 	output = 'default:axe_wood', | ||||
| 	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({ | ||||
| 	output = 'default:sword_wood', | ||||
| 	recipe = { | ||||
| @@ -904,7 +853,7 @@ minetest.register_craft({ | ||||
| -- Fuels | ||||
| -- | ||||
|  | ||||
| -- Support use of group:tree | ||||
| -- Support use of group:tree, includes default:tree which has the same burn time | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "group:tree", | ||||
| @@ -927,12 +876,6 @@ minetest.register_craft({ | ||||
| 	burntime = 26, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:tree", | ||||
| 	burntime = 30, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	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({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "group:wood", | ||||
| @@ -965,12 +908,6 @@ minetest.register_craft({ | ||||
| 	burntime = 6, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:wood", | ||||
| 	burntime = 7, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	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({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "group:sapling", | ||||
| 	burntime = 10, | ||||
| 	burntime = 5, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:bush_sapling", | ||||
| 	burntime = 6, | ||||
| 	burntime = 3, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:acacia_bush_sapling", | ||||
| 	burntime = 7, | ||||
| 	burntime = 4, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:aspen_sapling", | ||||
| 	burntime = 8, | ||||
| 	burntime = 4, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:pine_sapling", | ||||
| 	burntime = 9, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:sapling", | ||||
| 	burntime = 10, | ||||
| 	burntime = 5, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:acacia_sapling", | ||||
| 	burntime = 11, | ||||
| 	burntime = 6, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:junglesapling", | ||||
| 	burntime = 12, | ||||
| 	burntime = 6, | ||||
| }) | ||||
|  | ||||
|  | ||||
| @@ -1080,13 +1011,13 @@ minetest.register_craft({ | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:junglegrass", | ||||
| 	burntime = 2, | ||||
| 	burntime = 3, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "group:leaves", | ||||
| 	burntime = 1, | ||||
| 	burntime = 4, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| @@ -1098,7 +1029,7 @@ minetest.register_craft({ | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:papyrus", | ||||
| 	burntime = 1, | ||||
| 	burntime = 3, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| @@ -1110,7 +1041,7 @@ minetest.register_craft({ | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:ladder_wood", | ||||
| 	burntime = 2, | ||||
| 	burntime = 7, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| @@ -1143,12 +1074,6 @@ minetest.register_craft({ | ||||
| 	burntime = 30, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:apple", | ||||
| 	burntime = 3, | ||||
| }) | ||||
|  | ||||
| minetest.register_craft({ | ||||
| 	type = "fuel", | ||||
| 	recipe = "default:coal_lump", | ||||
|   | ||||
| @@ -75,12 +75,16 @@ local function book_on_use(itemstack, user) | ||||
| 	return itemstack | ||||
| 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) | ||||
| 	if formname ~= "default:book" then return end | ||||
| 	local inv = player:get_inventory() | ||||
| 	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 | ||||
| 		if stack:get_name() ~= "default:book_written" then | ||||
| 			local count = stack:get_count() | ||||
| @@ -99,11 +103,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) | ||||
| 		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.description = "\""..fields.title.."\" by "..data.owner | ||||
| 		data.text = fields.text | ||||
| 		data.text_len = #data.text | ||||
| 		local short_title = data.title | ||||
| 		-- Don't bother triming the title if the trailing dots would make it longer | ||||
| 		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_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", | ||||
| 		nodenames = {"default:lava_source", "default:lava_flowing"}, | ||||
| 		neighbors = {"group:cools_lava", "group:water"}, | ||||
| 		interval = 1, | ||||
| 		interval = 2, | ||||
| 		chance = 2, | ||||
| 		catch_up = false, | ||||
| 		action = default.cool_lava, | ||||
| 		action = function(...) | ||||
| 			default.cool_lava(...) | ||||
| 		end, | ||||
| 	}) | ||||
| end | ||||
|  | ||||
| @@ -222,7 +224,9 @@ minetest.register_abm({ | ||||
| 	neighbors = {"group:sand"}, | ||||
| 	interval = 12, | ||||
| 	chance = 83, | ||||
| 	action = default.grow_cactus | ||||
| 	action = function(...) | ||||
| 		default.grow_cactus(...) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
| minetest.register_abm({ | ||||
| @@ -231,7 +235,9 @@ minetest.register_abm({ | ||||
| 	neighbors = {"default:dirt", "default:dirt_with_grass"}, | ||||
| 	interval = 14, | ||||
| 	chance = 71, | ||||
| 	action = default.grow_papyrus | ||||
| 	action = function(...) | ||||
| 		default.grow_papyrus(...) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| @@ -291,7 +297,7 @@ function default.register_fence(name, def) | ||||
| 		groups = {}, | ||||
| 	} | ||||
| 	for k, v in pairs(default_fields) do | ||||
| 		if not def[k] then | ||||
| 		if def[k] == nil then | ||||
| 			def[k] = v | ||||
| 		end | ||||
| 	end | ||||
| @@ -313,7 +319,7 @@ end | ||||
| -- Prevent decay of placed leaves | ||||
|  | ||||
| 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) | ||||
| 		node.param2 = 1 | ||||
| 		minetest.set_node(pos, node) | ||||
|   | ||||
| @@ -119,7 +119,7 @@ local function furnace_node_timer(pos, elapsed) | ||||
| 	local fuel | ||||
|  | ||||
| 	local update = true | ||||
| 	while update do | ||||
| 	while elapsed > 0 and update do | ||||
| 		update = false | ||||
|  | ||||
| 		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}) | ||||
| 		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 | ||||
| 		if fuel_time < fuel_totaltime then | ||||
| 			-- 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 cookable then | ||||
| 				src_time = src_time + elapsed | ||||
| 				src_time = src_time + el | ||||
| 				if src_time >= cooked.time then | ||||
| 					-- Place result in dst list if possible | ||||
| 					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 | ||||
| 						update = true | ||||
| 					end | ||||
| 				else | ||||
| 					-- Item could not be cooked: probably missing fuel | ||||
| 					update = true | ||||
| 				end | ||||
| 			end | ||||
| 		else | ||||
| @@ -166,8 +174,7 @@ local function furnace_node_timer(pos, elapsed) | ||||
| 					-- Take fuel from fuel list | ||||
| 					inv:set_stack("fuel", 1, afterfuel.items[1]) | ||||
| 					update = true | ||||
| 					fuel_totaltime = fuel.time + (fuel_time - fuel_totaltime) | ||||
| 					src_time = src_time + elapsed | ||||
| 					fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time) | ||||
| 				end | ||||
| 			else | ||||
| 				-- 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 | ||||
| 		end | ||||
|  | ||||
| 		elapsed = 0 | ||||
| 		elapsed = elapsed - el | ||||
| 	end | ||||
|  | ||||
| 	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) | ||||
| Copyright (C) 2010-2016: | ||||
| Copyright (C) 2010-2017: | ||||
|   celeron55, Perttu Ahola <celeron55@gmail.com> | ||||
|   Cisoun | ||||
|   G4JC | ||||
| @@ -44,6 +44,7 @@ Copyright (C) 2010-2016: | ||||
|   GreenXenith | ||||
|   kaeza | ||||
|   kilbith | ||||
|   CloudyProton | ||||
|  | ||||
| You are free to: | ||||
| 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) | ||||
| Copyright (C) 2014-2016 Neuromancer | ||||
|  | ||||
|  | ||||
| You are free to: | ||||
| Share — copy and redistribute the material in any medium or format. | ||||
| 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", | ||||
| 		{name = "default_dirt.png^default_snow_side.png", | ||||
| 			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', | ||||
| 	sounds = default.node_sound_dirt_defaults({ | ||||
| 		footstep = {name = "default_snow_footstep", gain = 0.15}, | ||||
| @@ -608,7 +608,7 @@ minetest.register_node("default:sapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -673,9 +673,7 @@ minetest.register_node("default:apple", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	after_place_node = function(pos, placer, itemstack) | ||||
| 		if placer:is_player() then | ||||
| 			minetest.set_node(pos, {name = "default:apple", param2 = 1}) | ||||
| 		end | ||||
| 		minetest.set_node(pos, {name = "default:apple", param2 = 1}) | ||||
| 	end, | ||||
| }) | ||||
|  | ||||
| @@ -742,7 +740,7 @@ minetest.register_node("default:junglesapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -821,7 +819,7 @@ minetest.register_node("default:pine_sapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -901,7 +899,7 @@ minetest.register_node("default:acacia_sapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -979,7 +977,7 @@ minetest.register_node("default:aspen_sapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -1362,7 +1360,7 @@ minetest.register_node("default:bush_sapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -1433,7 +1431,7 @@ minetest.register_node("default:acacia_bush_sapling", { | ||||
| 	sounds = default.node_sound_leaves_defaults(), | ||||
|  | ||||
| 	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, | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| @@ -1783,13 +1781,14 @@ local function get_chest_formspec(pos) | ||||
| end | ||||
|  | ||||
| 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] | ||||
| 	-- 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 == "torchlike" or | ||||
| 			(def.drawtype == "nodebox" and def.paramtype2 == "wallmounted") then | ||||
| 			(def.drawtype == "nodebox" and def.paramtype2 == "wallmounted")) then | ||||
| 		return false | ||||
| 	end | ||||
| 	return true | ||||
| @@ -1797,6 +1796,24 @@ end | ||||
|  | ||||
| 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) | ||||
| 	if formname ~= "default:chest" then | ||||
| 		return | ||||
| @@ -1810,23 +1827,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	local pos = open_chests[pn].pos | ||||
| 	local sound = open_chests[pn].sound | ||||
| 	local swap = open_chests[pn].swap | ||||
| 	local node = minetest.get_node(pos) | ||||
|  | ||||
| 	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 | ||||
| 	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}) | ||||
| 	chest_lid_close(pn) | ||||
| 	return true | ||||
| end) | ||||
|  | ||||
| minetest.register_on_leaveplayer(function(player) | ||||
| 	local pn = player:get_player_name() | ||||
| 	if open_chests[pn] then | ||||
| 		chest_lid_close(pn) | ||||
| 	end | ||||
| end) | ||||
|  | ||||
| function default.register_chest(name, d) | ||||
| 	local def = table.copy(d) | ||||
| 	def.drawtype = "mesh" | ||||
| @@ -1960,6 +1971,13 @@ function default.register_chest(name, d) | ||||
| 			open_chests[clicker:get_player_name()] = { pos = pos, | ||||
| 					sound = def.sound_close, swap = name } | ||||
| 		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 | ||||
|  | ||||
| 	def.on_metadata_inventory_move = function(pos, from_list, from_index, | ||||
| @@ -1977,27 +1995,28 @@ function default.register_chest(name, d) | ||||
| 			" takes " .. stack:get_name() .. | ||||
| 			" from chest at " .. minetest.pos_to_string(pos)) | ||||
| 	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_closed = table.copy(def) | ||||
|  | ||||
| 	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.groups.not_in_creative_inventory = 1 | ||||
| 	def_opened.selection_box = { | ||||
| 		type = "fixed", | ||||
| 		fixed = { -1/2, -1/2, -1/2, 1/2, 3/16, 1/2 }, | ||||
| 		} | ||||
| 	} | ||||
| 	def_opened.can_dig = function() | ||||
| 		return false | ||||
| 	end | ||||
| 	def_opened.on_blast = function() end | ||||
|  | ||||
| 	def_closed.mesh = 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 def = minetest.registered_nodes[node.name] | ||||
| 		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, | ||||
| 				pointed_thing) or itemstack | ||||
| 		end | ||||
|   | ||||
| @@ -63,7 +63,8 @@ minetest.register_node("default:torch", { | ||||
| 		local node = minetest.get_node(under) | ||||
| 		local def = minetest.registered_nodes[node.name] | ||||
| 		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, | ||||
| 				pointed_thing) or itemstack | ||||
| 		end | ||||
|   | ||||
| @@ -31,12 +31,12 @@ local function is_snow_nearby(pos) | ||||
| end | ||||
|  | ||||
|  | ||||
| -- Sapling ABM | ||||
| -- Grow sapling | ||||
|  | ||||
| function default.grow_sapling(pos) | ||||
| 	if not default.can_grow(pos) then | ||||
| 		-- try a bit later again | ||||
| 		minetest.get_node_timer(pos):start(math.random(240, 600)) | ||||
| 		-- try again 5 min later | ||||
| 		minetest.get_node_timer(pos):start(300) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| @@ -94,7 +94,7 @@ minetest.register_lbm({ | ||||
| 			"default:pine_sapling", "default:acacia_sapling", | ||||
| 			"default:aspen_sapling"}, | ||||
| 	action = function(pos) | ||||
| 		minetest.get_node_timer(pos):start(math.random(1200, 2400)) | ||||
| 		minetest.get_node_timer(pos):start(math.random(300, 1500)) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
| @@ -468,7 +468,9 @@ function default.sapling_on_place(itemstack, placer, pointed_thing, | ||||
| 	local node = minetest.get_node_or_nil(pos) | ||||
| 	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) | ||||
| 	end | ||||
|  | ||||
| @@ -481,7 +483,7 @@ function default.sapling_on_place(itemstack, placer, pointed_thing, | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local player_name = placer:get_player_name() | ||||
| 	local player_name = placer and placer:get_player_name() or "" | ||||
| 	-- Check sapling position for protection | ||||
| 	if minetest.is_protected(pos, player_name) then | ||||
| 		minetest.record_protection_violation(pos, player_name) | ||||
|   | ||||
| @@ -203,12 +203,7 @@ end | ||||
|  | ||||
| local function can_dig_door(pos, digger) | ||||
| 	replace_old_owner_information(pos) | ||||
| 	if default.can_interact_with_node(digger, pos) then | ||||
| 		return true | ||||
| 	else | ||||
| 		minetest.record_protection_violation(pos, digger:get_player_name()) | ||||
| 		return false | ||||
| 	end | ||||
| 	return default.can_interact_with_node(digger, pos) | ||||
| end | ||||
|  | ||||
| function doors.register(name, def) | ||||
| @@ -266,7 +261,8 @@ function doors.register(name, def) | ||||
| 			local node = minetest.get_node(pointed_thing.under) | ||||
| 			local pdef = minetest.registered_nodes[node.name] | ||||
| 			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, | ||||
| 						node, placer, itemstack, pointed_thing) | ||||
| 			end | ||||
| @@ -290,12 +286,12 @@ function doors.register(name, def) | ||||
| 				return itemstack | ||||
| 			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 | ||||
| 				return itemstack | ||||
| 			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 = { | ||||
| 				{x = -1, y = 0, z = 0}, | ||||
| @@ -712,7 +708,7 @@ function doors.register_fencegate(name, def) | ||||
| 	local fence = { | ||||
| 		description = def.description, | ||||
| 		drawtype = "mesh", | ||||
| 		tiles = {def.texture}, | ||||
| 		tiles = {}, | ||||
| 		paramtype = "light", | ||||
| 		paramtype2 = "facedir", | ||||
| 		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 | ||||
| 		fence.sounds = default.node_sound_wood_defaults() | ||||
| 	end | ||||
|   | ||||
| @@ -118,15 +118,6 @@ farming.register_hoe = function(name, def) | ||||
| 				{"", "group:stick", ""} | ||||
| 			} | ||||
| 		}) | ||||
| 		-- Reverse Recipe | ||||
| 		minetest.register_craft({ | ||||
| 			output = name:sub(2), | ||||
| 			recipe = { | ||||
| 				{"", def.material, def.material}, | ||||
| 				{"", "group:stick", ""}, | ||||
| 				{"", "group:stick", ""} | ||||
| 			} | ||||
| 		}) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -153,12 +144,14 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname) | ||||
| 	local under = minetest.get_node(pt.under) | ||||
| 	local above = minetest.get_node(pt.above) | ||||
|  | ||||
| 	if minetest.is_protected(pt.under, placer:get_player_name()) then | ||||
| 		minetest.record_protection_violation(pt.under, placer:get_player_name()) | ||||
| 	local player_name = placer and placer:get_player_name() or "" | ||||
|  | ||||
| 	if minetest.is_protected(pt.under, player_name) then | ||||
| 		minetest.record_protection_violation(pt.under, player_name) | ||||
| 		return | ||||
| 	end | ||||
| 	if minetest.is_protected(pt.above, placer:get_player_name()) then | ||||
| 		minetest.record_protection_violation(pt.above, placer:get_player_name()) | ||||
| 	if minetest.is_protected(pt.above, player_name) then | ||||
| 		minetest.record_protection_violation(pt.above, player_name) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| @@ -189,7 +182,7 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname) | ||||
| 	minetest.add_node(pt.above, {name = plantname, param2 = 1}) | ||||
| 	tick(pt.above) | ||||
| 	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() | ||||
| 	end | ||||
| 	return itemstack | ||||
| @@ -319,7 +312,8 @@ farming.register_plant = function(name, def) | ||||
| 			local node = minetest.get_node(under) | ||||
| 			local udef = minetest.registered_nodes[node.name] | ||||
| 			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, | ||||
| 					pointed_thing) or itemstack | ||||
| 			end | ||||
|   | ||||
| @@ -1,2 +1,3 @@ | ||||
| default | ||||
| wool | ||||
| stairs | ||||
|   | ||||
| @@ -98,6 +98,16 @@ minetest.register_node("farming:straw", { | ||||
| 	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({ | ||||
| 	label = "Farming soil", | ||||
| 	nodenames = {"group:field"}, | ||||
|   | ||||
| @@ -127,24 +127,29 @@ function flowers.flower_spread(pos, node) | ||||
|  | ||||
| 	local pos0 = vector.subtract(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 | ||||
| 	end | ||||
|  | ||||
| 	local soils = minetest.find_nodes_in_area_under_air( | ||||
| 		pos0, pos1, "group:soil") | ||||
| 	if #soils > 0 then | ||||
| 		local seedling = soils[math.random(#soils)] | ||||
| 		local seedling_above = | ||||
| 			{x = seedling.x, y = seedling.y + 1, z = seedling.z} | ||||
| 		light = minetest.get_node_light(seedling_above) | ||||
| 		if not light or light < 13 or | ||||
| 				-- Desert sand is in the soil group | ||||
| 				minetest.get_node(seedling).name == "default:desert_sand" then | ||||
| 			return | ||||
| 	local num_soils = #soils | ||||
| 	if num_soils >= 1 then | ||||
| 		for si = 1, math.min(3, num_soils) do | ||||
| 			local soil = soils[math.random(num_soils)] | ||||
| 			local soil_above = {x = soil.x, y = soil.y + 1, z = soil.z} | ||||
| 			light = minetest.get_node_light(soil_above) | ||||
| 			if light and light >= 13 and | ||||
| 					-- Desert sand is in the soil group | ||||
| 					minetest.get_node(soil).name ~= "default:desert_sand" then | ||||
| 				minetest.set_node(soil_above, {name = node.name}) | ||||
| 			end | ||||
| 		end | ||||
|  | ||||
| 		minetest.set_node(seedling_above, {name = node.name}) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -152,7 +157,7 @@ minetest.register_abm({ | ||||
| 	label = "Flower spread", | ||||
| 	nodenames = {"group:flora"}, | ||||
| 	interval = 13, | ||||
| 	chance = 96, | ||||
| 	chance = 300, | ||||
| 	action = function(...) | ||||
| 		flowers.flower_spread(...) | ||||
| 	end, | ||||
| @@ -204,38 +209,34 @@ minetest.register_node("flowers:mushroom_brown", { | ||||
|  | ||||
| -- Mushroom spread and death | ||||
|  | ||||
| function flowers.mushroom_spread(pos, node) | ||||
| 	if minetest.get_node_light(pos, nil) == 15 then | ||||
| 		minetest.remove_node(pos) | ||||
| 		return | ||||
| 	end | ||||
| 	local positions = minetest.find_nodes_in_area_under_air( | ||||
| 		{x = pos.x - 1, y = pos.y - 2, z = pos.z - 1}, | ||||
| 		{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, | ||||
| 		{"group:soil", "group:tree"}) | ||||
| 	if #positions == 0 then | ||||
| 		return | ||||
| 	end | ||||
| 	local pos2 = positions[math.random(#positions)] | ||||
| 	pos2.y = pos2.y + 1 | ||||
| 	if minetest.get_node_light(pos, 0.5) <= 3 and | ||||
| 			minetest.get_node_light(pos2, 0.5) <= 3 then | ||||
| 		minetest.set_node(pos2, {name = node.name}) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| minetest.register_abm({ | ||||
| 	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 | ||||
| 			minetest.remove_node(pos) | ||||
| 			return | ||||
| 		end | ||||
| 		local random = { | ||||
| 			x = pos.x + math.random(-2, 2), | ||||
| 			y = pos.y + math.random(-1, 1), | ||||
| 			z = pos.z + math.random(-2, 2) | ||||
| 		} | ||||
| 		local random_node = minetest.get_node_or_nil(random) | ||||
| 		if not random_node or random_node.name ~= "air" then | ||||
| 			return | ||||
| 		end | ||||
| 		local node_under = minetest.get_node_or_nil({x = random.x, | ||||
| 			y = random.y - 1, z = random.z}) | ||||
| 		if not node_under then | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		if (minetest.get_item_group(node_under.name, "soil") ~= 0 or | ||||
| 				minetest.get_item_group(node_under.name, "tree") ~= 0) and | ||||
| 				minetest.get_node_light(pos, 0.5) <= 3 and | ||||
| 				minetest.get_node_light(random, 0.5) <= 3 then | ||||
| 			minetest.set_node(random, {name = node.name}) | ||||
| 		end | ||||
| 	end | ||||
| 	chance = 150, | ||||
| 	action = function(...) | ||||
| 		flowers.mushroom_spread(...) | ||||
| 	end, | ||||
| }) | ||||
|  | ||||
|  | ||||
| @@ -280,12 +281,17 @@ minetest.register_node("flowers:waterlily", { | ||||
|  | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| 		local pos = pointed_thing.above | ||||
| 		local node = minetest.get_node(pointed_thing.under).name | ||||
| 		local def = minetest.registered_nodes[node] | ||||
| 		local player_name = placer:get_player_name() | ||||
| 		local node = minetest.get_node(pointed_thing.under) | ||||
| 		local def = minetest.registered_nodes[node.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 | ||||
| 				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 | ||||
| 				minetest.set_node(pos, {name = "flowers:waterlily", | ||||
| 					param2 = math.random(0, 3)}) | ||||
|   | ||||
| @@ -85,9 +85,10 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) | ||||
| 	end | ||||
|  | ||||
| 	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 | ||||
| 		minetest.record_protection_violation(pos, user:get_player_name()) | ||||
| 	if minetest.is_protected(pos, player_name) then | ||||
| 		minetest.record_protection_violation(pos, player_name) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| @@ -133,8 +134,8 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) | ||||
| 		minetest.check_for_falling(pos) | ||||
| 	end | ||||
|  | ||||
| 	if not (creative and creative.is_enabled_for | ||||
| 			and creative.is_enabled_for(user:get_player_name())) then | ||||
| 	if not (creative and creative.is_enabled_for and | ||||
| 			creative.is_enabled_for(player_name)) then | ||||
| 		itemstack:add_wear(65535 / ((uses or 200) - 1)) | ||||
| 	end | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,8 @@ end | ||||
| function sfinv.get_nav_fs(player, context, nav, current_idx) | ||||
| 	-- Only show tabs if there is more than one page | ||||
| 	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 | ||||
| 		return "" | ||||
| 	end | ||||
| @@ -84,9 +85,20 @@ function sfinv.get_formspec(player, context) | ||||
| 		return page:get(player, context) | ||||
| 	else | ||||
| 		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") | ||||
| 		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) | ||||
| 	end | ||||
| end | ||||
| @@ -151,8 +163,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) | ||||
| 	end | ||||
|  | ||||
| 	-- Was a tab selected? | ||||
| 	if fields.tabs and context.nav then | ||||
| 		local tid = tonumber(fields.tabs) | ||||
| 	if fields.sfinv_nav_tabs and context.nav then | ||||
| 		local tid = tonumber(fields.sfinv_nav_tabs) | ||||
| 		if tid and tid > 0 then | ||||
| 			local id = context.nav[tid] | ||||
| 			local page = sfinv.pages[id] | ||||
|   | ||||
| @@ -1,2 +1 @@ | ||||
| default | ||||
| farming | ||||
|   | ||||
| @@ -22,21 +22,23 @@ local function rotate_and_place(itemstack, placer, pointed_thing) | ||||
| 	local p1 = pointed_thing.above | ||||
| 	local param2 = 0 | ||||
|  | ||||
| 	local placer_pos = placer:getpos() | ||||
| 	if placer_pos then | ||||
| 		param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) | ||||
| 	end | ||||
| 	if placer then | ||||
| 		local placer_pos = placer:getpos() | ||||
| 		if placer_pos then | ||||
| 			param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) | ||||
| 		end | ||||
|  | ||||
| 	local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) | ||||
| 	local fpos = finepos.y % 1 | ||||
| 		local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) | ||||
| 		local fpos = finepos.y % 1 | ||||
|  | ||||
| 	if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) | ||||
| 			or (fpos < -0.5 and fpos > -0.999999999) then | ||||
| 		param2 = param2 + 20 | ||||
| 		if param2 == 21 then | ||||
| 			param2 = 23 | ||||
| 		elseif param2 == 23 then | ||||
| 			param2 = 21 | ||||
| 		if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) | ||||
| 				or (fpos < -0.5 and fpos > -0.999999999) then | ||||
| 			param2 = param2 + 20 | ||||
| 			if param2 == 21 then | ||||
| 				param2 = 23 | ||||
| 			elseif param2 == 23 then | ||||
| 				param2 = 21 | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 	return minetest.item_place(itemstack, placer, pointed_thing, param2) | ||||
| @@ -46,16 +48,29 @@ end | ||||
| -- Node will be called stairs:stair_<subname> | ||||
|  | ||||
| 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, { | ||||
| 		description = description, | ||||
| 		drawtype = "mesh", | ||||
| 		mesh = "stairs_stair.obj", | ||||
| 		tiles = images, | ||||
| 		tiles = stair_images, | ||||
| 		paramtype = "light", | ||||
| 		paramtype2 = "facedir", | ||||
| 		is_ground_content = false, | ||||
| 		groups = groups, | ||||
| 		groups = new_groups, | ||||
| 		sounds = sounds, | ||||
| 		selection_box = { | ||||
| 			type = "fixed", | ||||
| @@ -89,16 +104,7 @@ function stairs.register_stair(subname, recipeitem, groups, images, description, | ||||
| 	end | ||||
|  | ||||
| 	if recipeitem then | ||||
| 		minetest.register_craft({ | ||||
| 			output = 'stairs:stair_' .. subname .. ' 8', | ||||
| 			recipe = { | ||||
| 				{recipeitem, "", ""}, | ||||
| 				{recipeitem, recipeitem, ""}, | ||||
| 				{recipeitem, recipeitem, recipeitem}, | ||||
| 			}, | ||||
| 		}) | ||||
|  | ||||
| 		-- Flipped recipe for the silly minecrafters | ||||
| 		-- Recipe matches appearence in inventory | ||||
| 		minetest.register_craft({ | ||||
| 			output = 'stairs:stair_' .. subname .. ' 8', | ||||
| 			recipe = { | ||||
| @@ -132,7 +138,8 @@ local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4} | ||||
| -- Node will be called stairs:slab_<subname> | ||||
|  | ||||
| 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, { | ||||
| 		description = description, | ||||
| 		drawtype = "nodebox", | ||||
| @@ -140,7 +147,7 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, | ||||
| 		paramtype = "light", | ||||
| 		paramtype2 = "facedir", | ||||
| 		is_ground_content = false, | ||||
| 		groups = groups, | ||||
| 		groups = new_groups, | ||||
| 		sounds = sounds, | ||||
| 		node_box = { | ||||
| 			type = "fixed", | ||||
| @@ -149,8 +156,9 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, | ||||
| 		on_place = function(itemstack, placer, pointed_thing) | ||||
| 			local under = minetest.get_node(pointed_thing.under) | ||||
| 			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 | ||||
| 					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 | ||||
| 				-- place slab using under node orientation | ||||
| @@ -166,9 +174,8 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, | ||||
| 					if not recipeitem then | ||||
| 						return itemstack | ||||
| 					end | ||||
| 					local player_name = placer:get_player_name() | ||||
| 					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, | ||||
| 							player_name) | ||||
| 						return | ||||
| @@ -538,16 +545,6 @@ stairs.register_stair_and_slab( | ||||
| 	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( | ||||
| 	"steelblock", | ||||
| 	"default:steelblock", | ||||
|   | ||||
| @@ -86,8 +86,8 @@ end | ||||
| local basic_flame_on_construct -- cached value | ||||
| local function destroy(drops, npos, cid, c_air, c_fire, | ||||
| 		on_blast_queue, on_construct_queue, | ||||
| 		ignore_protection, ignore_on_blast) | ||||
| 	if not ignore_protection and minetest.is_protected(npos, "") then | ||||
| 		ignore_protection, ignore_on_blast, owner) | ||||
| 	if not ignore_protection and minetest.is_protected(npos, owner) then | ||||
| 		return cid | ||||
| 	end | ||||
|  | ||||
| @@ -208,6 +208,7 @@ local function add_effects(pos, radius, drops) | ||||
| 		collisiondetection = false, | ||||
| 		vertical = false, | ||||
| 		texture = "tnt_boom.png", | ||||
| 		glow = 15, | ||||
| 	}) | ||||
| 	minetest.add_particlespawner({ | ||||
| 		amount = 64, | ||||
| @@ -266,13 +267,13 @@ function tnt.burn(pos, nodename) | ||||
| 	elseif def.on_ignite then | ||||
| 		def.on_ignite(pos) | ||||
| 	elseif minetest.get_item_group(name, "tnt") > 0 then | ||||
| 		minetest.swap_node(pos, {name = name .. "_burning"}) | ||||
| 		minetest.sound_play("tnt_ignite", {pos = pos}) | ||||
| 		minetest.set_node(pos, {name = name .. "_burning"}) | ||||
| 		minetest.get_node_timer(pos):start(1) | ||||
| 	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) | ||||
| 	-- scan for adjacent TNT nodes first, and enlarge the explosion | ||||
| 	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_boom = minetest.get_content_id("tnt:boom") | ||||
| 	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 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 | ||||
| 				data[vi] = destroy(drops, p, cid, c_air, c_fire, | ||||
| 					on_blast_queue, on_construct_queue, | ||||
| 					ignore_protection, ignore_on_blast) | ||||
| 					ignore_protection, ignore_on_blast, owner) | ||||
| 			end | ||||
| 		end | ||||
| 		vi = vi + 1 | ||||
| @@ -375,16 +380,26 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) | ||||
| 		queued_data.fn(queued_data.pos) | ||||
| 	end | ||||
|  | ||||
| 	minetest.log("action", "TNT owned by " .. owner .. " detonated at " .. | ||||
| 		minetest.pos_to_string(pos) .. " with radius " .. radius) | ||||
|  | ||||
| 	return drops, radius | ||||
| end | ||||
|  | ||||
| function tnt.boom(pos, def) | ||||
| 	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"}) | ||||
| 	end | ||||
| 	minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 2*64}) | ||||
| 	minetest.set_node(pos, {name = "tnt:boom"}) | ||||
| 	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 | ||||
| 	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) | ||||
| 	if not def.disable_drops then | ||||
| 		eject_drops(drops, pos, radius) | ||||
| @@ -400,12 +415,6 @@ minetest.register_node("tnt:boom", { | ||||
| 	walkable = false, | ||||
| 	drop = "", | ||||
| 	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 | ||||
| 	on_blast = function() end, | ||||
| }) | ||||
| @@ -508,17 +517,17 @@ minetest.register_node("tnt:gunpowder_burning", { | ||||
| 	on_timer = function(pos, elapsed) | ||||
| 		for dx = -1, 1 do | ||||
| 		for dz = -1, 1 do | ||||
| 		for dy = -1, 1 do | ||||
| 			if not (dx == 0 and dz == 0) then | ||||
| 				tnt.burn({ | ||||
| 					x = pos.x + dx, | ||||
| 					y = pos.y + dy, | ||||
| 					z = pos.z + dz, | ||||
| 				}) | ||||
| 			if math.abs(dx) + math.abs(dz) == 1 then | ||||
| 				for dy = -1, 1 do | ||||
| 					tnt.burn({ | ||||
| 						x = pos.x + dx, | ||||
| 						y = pos.y + dy, | ||||
| 						z = pos.z + dz, | ||||
| 					}) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 		end | ||||
| 		end | ||||
| 		minetest.remove_node(pos) | ||||
| 	end, | ||||
| 	-- unaffected by explosions | ||||
| @@ -579,9 +588,16 @@ function tnt.register_tnt(def) | ||||
| 			is_ground_content = false, | ||||
| 			groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5}, | ||||
| 			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) | ||||
| 				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() .. | ||||
| 						" ignites " .. node.name .. " at " .. | ||||
| 						minetest.pos_to_string(pos)) | ||||
| @@ -600,10 +616,12 @@ function tnt.register_tnt(def) | ||||
| 				} | ||||
| 			}, | ||||
| 			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, | ||||
| 			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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user