mirror of
				https://github.com/mt-mods/homedecor_modpack.git
				synced 2025-10-31 04:15:35 +01:00 
			
		
		
		
	rewrite the node stacking/expansion code, preventing a crash building on unknown nodes, and reduce table lookups and overall code
This commit is contained in:
		
							
								
								
									
										81
									
								
								homedecor/expansion.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								homedecor/expansion.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| -- returns the correct buildable_to node | ||||
| local function get_buildable_to(pointed_thing) | ||||
| 	local pos = pointed_thing.under | ||||
| 	local def = minetest.registered_nodes[minetest.get_node(pos).name] | ||||
|  | ||||
| 	if not def or not def.buildable_to then | ||||
| 		pos = pointed_thing.above | ||||
| 		def = minetest.registered_nodes[minetest.get_node(pos).name] | ||||
| 	end | ||||
| 	return pos, def | ||||
| end | ||||
|  | ||||
| -- abstract function checking if 2 given nodes can and may be build to a place | ||||
| local function is_buildable_to(placer_name, pos, def, pos2) | ||||
| 	local def = def or minetest.registered_nodes[minetest.get_node(pos).name] | ||||
| 	local def2 = minetest.registered_nodes[minetest.get_node(pos2).name] | ||||
|  | ||||
| 	return def and def.buildable_to and def2 and def2.buildable_to | ||||
| 		and not minetest.is_protected(pos, placer_name) | ||||
| 		and not minetest.is_protected(pos2, placer_name) | ||||
| end | ||||
|  | ||||
| -- place one or two nodes if and only if both can be placed | ||||
| local function stack(itemstack, placer, fdir, pos, def, pos2, node1, node2) | ||||
| 	local placer_name = placer:get_player_name() or "" | ||||
| 	if is_buildable_to(placer_name, pos, def, pos2) then | ||||
| 		local fdir = fdir or minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 		minetest.set_node(pos, { name = node1, param2 = fdir }) | ||||
|  | ||||
| 		if node2 then | ||||
| 			minetest.set_node(pos2, { name = node2, param2 = fdir }) | ||||
| 		end | ||||
|  | ||||
| 		-- temporary check if this is a locked node to set its infotext | ||||
| 		local nodename = itemstack:get_name() | ||||
| 		if string.find(nodename, "_locked") then | ||||
| 			local meta = minetest.get_meta(pos) | ||||
| 			meta:set_string("owner", placer_name) | ||||
| 			meta:set_string("infotext", S("Locked Refrigerator (owned by %s)"):format(placer_name)) | ||||
| 		end | ||||
|  | ||||
| 		if not homedecor.expect_infinite_stacks then | ||||
| 			itemstack:take_item() | ||||
| 			return itemstack | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Stack one node above another | ||||
| -- leave the last argument nil if it's one 2m high node | ||||
| function homedecor.stack_vertically(itemstack, placer, pointed_thing, node1, node2) | ||||
| 	local pos, def = get_buildable_to(pointed_thing) | ||||
| 	local top_pos = { x=pos.x, y=pos.y+1, z=pos.z } | ||||
|  | ||||
| 	return stack(itemstack, placer, nil, pos, def, top_pos, node1, node2) | ||||
| end | ||||
|  | ||||
| -- Place one node right of or behind another | ||||
| homedecor.fdir_to_right = { | ||||
| 	{  1,  0 }, | ||||
| 	{  0, -1 }, | ||||
| 	{ -1,  0 }, | ||||
| 	{  0,  1 }, | ||||
| } | ||||
|  | ||||
| homedecor.fdir_to_fwd = { | ||||
| 	{  0,  1 }, | ||||
| 	{  1,  0 }, | ||||
| 	{  0, -1 }, | ||||
| 	{ -1,  0 }, | ||||
| } | ||||
|  | ||||
| function homedecor.stack_sideways(itemstack, placer, pointed_thing, node1, node2, dir) | ||||
| 	local fdir = minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 	local fdir_transform = dir and homedecor.fdir_to_right or homedecor.fdir_to_fwd | ||||
|  | ||||
| 	local pos, def = get_buildable_to(pointed_thing) | ||||
| 	local pos2 = { x = pos.x + fdir_transform[fdir+1][1], y=pos.y, z = pos.z + fdir_transform[fdir+1][2] } | ||||
|  | ||||
| 	return stack(itemstack, placer, fdir, pos, def, pos2, node1, node2) | ||||
| end | ||||
| @@ -57,8 +57,6 @@ function homedecor.table_copy(t) | ||||
|     return nt | ||||
| end | ||||
|  | ||||
| -- | ||||
|  | ||||
| function homedecor.get_nodedef_field(nodename, fieldname) | ||||
| 	if not minetest.registered_nodes[nodename] then | ||||
| 		return nil | ||||
| @@ -66,114 +64,6 @@ function homedecor.get_nodedef_field(nodename, fieldname) | ||||
| 	return minetest.registered_nodes[nodename][fieldname] | ||||
| end | ||||
|  | ||||
| -- Place a two-node-tall single object (e.g. a floor lamp) | ||||
|  | ||||
| function homedecor.place_twonode_vertical(itemstack, placer, pointed_thing, node) | ||||
| 	local pos = pointed_thing.under | ||||
| 	local pnode = minetest.get_node(pointed_thing.under) | ||||
| 	local rnodedef = minetest.registered_nodes[pnode.name] | ||||
|  | ||||
| 	if not rnodedef["buildable_to"] then | ||||
| 		pos = pointed_thing.above | ||||
| 	end | ||||
|  | ||||
| 	local fdir = minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 	local pos2 = { x = pos.x, y=pos.y + 1, z = pos.z } | ||||
|  | ||||
| 	local tnode = minetest.get_node(pos) | ||||
| 	local tnode2 = minetest.get_node(pos2) | ||||
|  | ||||
| 	if homedecor.get_nodedef_field(tnode.name, "buildable_to") | ||||
| 	  and homedecor.get_nodedef_field(tnode2.name, "buildable_to") | ||||
| 	  and not minetest.is_protected(pos, placer:get_player_name()) | ||||
| 	  and not minetest.is_protected(pos2, placer:get_player_name()) then | ||||
| 		minetest.add_node(pos, { name = node, param2 = fdir }) | ||||
| 		if not homedecor.expect_infinite_stacks then | ||||
| 			itemstack:take_item() | ||||
| 			return itemstack | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Stack one node above another | ||||
|  | ||||
| function homedecor.stack_vertically(itemstack, placer, pointed_thing, node1, node2) | ||||
| 	local pos = pointed_thing.under | ||||
| 	local pnode = minetest.get_node(pointed_thing.under) | ||||
| 	local rnodedef = minetest.registered_nodes[pnode.name] | ||||
|  | ||||
| 	if not rnodedef["buildable_to"] then | ||||
| 		pos = pointed_thing.above | ||||
| 	end | ||||
|  | ||||
| 	local fdir = minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 	local pos2 = { x = pos.x, y=pos.y + 1, z = pos.z } | ||||
|  | ||||
| 	local tnode = minetest.get_node(pos) | ||||
| 	local tnode2 = minetest.get_node(pos2) | ||||
|  | ||||
| 	if homedecor.get_nodedef_field(tnode.name, "buildable_to") | ||||
| 	  and homedecor.get_nodedef_field(tnode2.name, "buildable_to") | ||||
| 	  and not minetest.is_protected(pos, placer:get_player_name()) | ||||
| 	  and not minetest.is_protected(pos2, placer:get_player_name()) then | ||||
| 		minetest.add_node(pos, { name = node1, param2 = fdir }) | ||||
| 		minetest.add_node(pos2, { name = node2, param2 = fdir }) | ||||
| 		if not homedecor.expect_infinite_stacks then | ||||
| 			itemstack:take_item() | ||||
| 			return itemstack | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Place one node right of or behind another | ||||
|  | ||||
| homedecor.fdir_to_right = { | ||||
| 	{  1,  0 }, | ||||
| 	{  0, -1 }, | ||||
| 	{ -1,  0 }, | ||||
| 	{  0,  1 }, | ||||
| } | ||||
|  | ||||
| homedecor.fdir_to_fwd = { | ||||
| 	{  0,  1 }, | ||||
| 	{  1,  0 }, | ||||
| 	{  0, -1 }, | ||||
| 	{ -1,  0 }, | ||||
| } | ||||
|  | ||||
| function homedecor.stack_sideways(itemstack, placer, pointed_thing, node1, node2, dir) | ||||
| 	local pos = pointed_thing.under | ||||
| 	local pnode = minetest.get_node(pointed_thing.under) | ||||
| 	local rnodedef = minetest.registered_nodes[pnode.name] | ||||
|  | ||||
| 	if not rnodedef["buildable_to"] then | ||||
| 		pos = pointed_thing.above | ||||
| 	end | ||||
|  | ||||
| 	local fdir = minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 	local pos2 | ||||
| 	if dir then | ||||
| 		pos2 = { x = pos.x + homedecor.fdir_to_right[fdir+1][1], y=pos.y, z = pos.z + homedecor.fdir_to_right[fdir+1][2] } | ||||
| 	else | ||||
| 		pos2 = { x = pos.x + homedecor.fdir_to_fwd[fdir+1][1], y=pos.y, z = pos.z + homedecor.fdir_to_fwd[fdir+1][2] } | ||||
| 	end | ||||
|  | ||||
| 	local tnode = minetest.get_node(pos) | ||||
| 	local tnode2 = minetest.get_node(pos2) | ||||
|  | ||||
| 	if homedecor.get_nodedef_field(tnode.name, "buildable_to") | ||||
| 	  and homedecor.get_nodedef_field(tnode2.name, "buildable_to") | ||||
| 	  and not minetest.is_protected(pos, placer:get_player_name()) | ||||
| 	  and not minetest.is_protected(pos2, placer:get_player_name()) then | ||||
| 		minetest.add_node(pos, { name = node1, param2 = fdir }) | ||||
| 		minetest.add_node(pos2, { name = node2, param2 = fdir }) | ||||
| 		if not homedecor.expect_infinite_stacks then | ||||
| 			itemstack:take_item() | ||||
| 			return itemstack | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Determine if the item being pointed at is the underside of a node (e.g a ceiling) | ||||
|  | ||||
| function homedecor.find_ceiling(itemstack, placer, pointed_thing) | ||||
| @@ -222,6 +112,9 @@ function homedecor.find_ceiling(itemstack, placer, pointed_thing) | ||||
| 	return isceiling, pos | ||||
| end | ||||
|  | ||||
| -- expand and unexpand decor | ||||
| dofile(homedecor.modpath.."/expansion.lua") | ||||
| -- glue it all together into a registration function | ||||
| dofile(homedecor.modpath.."/registration_handler.lua") | ||||
|  | ||||
| -- load various other components | ||||
|   | ||||
| @@ -456,7 +456,7 @@ local function reg_lamp(suffix, nxt, tilesuffix, light, color) | ||||
| 		selection_box = slamp_cbox, | ||||
| 		collision_box = slamp_cbox, | ||||
| 		on_place = function(itemstack, placer, pointed_thing) | ||||
| 			return homedecor.place_twonode_vertical(itemstack, placer, pointed_thing, | ||||
| 			return homedecor.place_vertically(itemstack, placer, pointed_thing, | ||||
| 				"homedecor:standing_lamp"..lampcolor.."_"..suffix) | ||||
| 		end, | ||||
| 		on_punch = function(pos, node, puncher) | ||||
|   | ||||
| @@ -54,39 +54,7 @@ homedecor.register("refrigerator_steel_bottom", { | ||||
| 		fixed = { -0.5, -0.5, -0.5, 0.5, 1.5, 0.5 } | ||||
| 	}, | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| 		local pos = pointed_thing.under | ||||
| 		local pnode = minetest.get_node(pointed_thing.under) | ||||
| 		local rnodedef = minetest.registered_nodes[pnode.name] | ||||
|  | ||||
| 		if not rnodedef["buildable_to"] then | ||||
| 			pos = pointed_thing.above | ||||
| 		end | ||||
|  | ||||
| 		local fdir = minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 		local pos2 = { x = pos.x, y=pos.y + 1, z = pos.z } | ||||
|  | ||||
| 		local tnode = minetest.get_node(pos) | ||||
| 		local tnode2 = minetest.get_node(pos2) | ||||
|  | ||||
| 		if homedecor.get_nodedef_field(tnode.name, "buildable_to") | ||||
| 		  and homedecor.get_nodedef_field(tnode2.name, "buildable_to") | ||||
| 		  and not minetest.is_protected(pos, placer:get_player_name()) | ||||
| 		  and not minetest.is_protected(pos2, placer:get_player_name()) then | ||||
| 			local nodename = itemstack:get_name() | ||||
| 			minetest.add_node(pos, { name = nodename, param2 = fdir }) | ||||
| 			minetest.add_node(pos2, { name = "homedecor:refrigerator_steel_top", param2 = fdir }) | ||||
|  | ||||
| 			if string.find(nodename, "_locked") then | ||||
| 		        local meta = minetest.get_meta(pos) | ||||
| 				meta:set_string("owner", placer:get_player_name() or "") | ||||
| 				meta:set_string("infotext", S("Locked Refrigerator (owned by %s)"):format(meta:get_string("owner"))) | ||||
| 			end | ||||
|  | ||||
| 			if not homedecor.expect_infinite_stacks then | ||||
| 				itemstack:take_item() | ||||
| 				return itemstack | ||||
| 			end | ||||
| 		end | ||||
| 		homedecor.stack_vertically(itemstack, placer, pointed_thing, "homedecor:refrigerator_steel_bottom", "homedecor:refrigerator_steel_top") | ||||
| 	end, | ||||
| 	after_dig_node = function(pos, oldnode, oldmetadata, digger) | ||||
| 		local pos2 = { x = pos.x, y=pos.y + 1, z = pos.z } | ||||
| @@ -97,6 +65,7 @@ homedecor.register("refrigerator_steel_bottom", { | ||||
| 	infotext=S("Refrigerator"), | ||||
| 	inventory = { | ||||
| 		size=50, | ||||
| 		lockable=true, | ||||
| 		formspec="size[10,10]".. | ||||
| 			"list[context;main;0,0;10,5;]".. | ||||
| 			"list[current_player;main;1,6;8,4;]", | ||||
| @@ -140,39 +109,7 @@ homedecor.register("refrigerator_white_bottom", { | ||||
| 		fixed = { -0.5, -0.5, -0.5, 0.5, 1.5, 0.5 } | ||||
| 	}, | ||||
| 	on_place = function(itemstack, placer, pointed_thing) | ||||
| 		local pos = pointed_thing.under | ||||
| 		local pnode = minetest.get_node(pointed_thing.under) | ||||
| 		local rnodedef = minetest.registered_nodes[pnode.name] | ||||
|  | ||||
| 		if not rnodedef["buildable_to"] then | ||||
| 			pos = pointed_thing.above | ||||
| 		end | ||||
|  | ||||
| 		local fdir = minetest.dir_to_facedir(placer:get_look_dir()) | ||||
| 		local pos2 = { x = pos.x, y=pos.y + 1, z = pos.z } | ||||
|  | ||||
| 		local tnode = minetest.get_node(pos) | ||||
| 		local tnode2 = minetest.get_node(pos2) | ||||
|  | ||||
| 		if homedecor.get_nodedef_field(tnode.name, "buildable_to") | ||||
| 		  and homedecor.get_nodedef_field(tnode2.name, "buildable_to") | ||||
| 		  and not minetest.is_protected(pos, placer:get_player_name()) | ||||
| 		  and not minetest.is_protected(pos2, placer:get_player_name()) then | ||||
| 			local nodename = itemstack:get_name() | ||||
| 			minetest.add_node(pos, { name = nodename, param2 = fdir }) | ||||
| 			minetest.add_node(pos2, { name = "homedecor:refrigerator_white_top", param2 = fdir }) | ||||
|  | ||||
| 			if string.find(nodename, "_locked") then | ||||
| 		        local meta = minetest.get_meta(pos) | ||||
| 				meta:set_string("owner", placer:get_player_name() or "") | ||||
| 				meta:set_string("infotext", S("Locked Refrigerator (owned by %s)"):format(meta:get_string("owner"))) | ||||
| 			end | ||||
|  | ||||
| 			if not homedecor.expect_infinite_stacks then | ||||
| 				itemstack:take_item() | ||||
| 				return itemstack | ||||
| 			end | ||||
| 		end | ||||
| 		homedecor.stack_vertically(itemstack, placer, pointed_thing, "homedecor:refrigerator_white_bottom", "homedecor:refrigerator_white_top") | ||||
| 	end, | ||||
| 	after_dig_node = function(pos, oldnode, oldmetadata, digger) | ||||
| 		local pos2 = { x = pos.x, y=pos.y + 1, z = pos.z } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user