diff --git a/mods/beds/api.lua b/mods/beds/api.lua
index be3cb97..e2dd7ed 100644
--- a/mods/beds/api.lua
+++ b/mods/beds/api.lua
@@ -44,23 +44,42 @@ function beds.register_bed(name, def)
 			fixed = def.selectionbox,
 		},
 
-		after_place_node = function(pos, placer, itemstack)
-			local n = minetest.get_node_or_nil(pos)
-			if not n or not n.param2 then
-				minetest.remove_node(pos)
-				return true
+		on_place = function(itemstack, placer, pointed_thing)
+			local under = pointed_thing.under
+			local pos
+			if minetest.registered_items[minetest.get_node(under).name].buildable_to then
+				pos = under
+			else
+				pos = pointed_thing.above
 			end
-			local dir = minetest.facedir_to_dir(n.param2)
-			local p = vector.add(pos, dir)
-			local n2 = minetest.get_node_or_nil(p)
-			local def = n2 and minetest.registered_items[n2.name]
-			if not def or not def.buildable_to then
-				minetest.remove_node(pos)
-				return true
+
+			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())
+				return itemstack
 			end
-			minetest.set_node(p, {name = n.name:gsub("%_bottom", "_top"), param2 = n.param2})
-			return false
-		end,	
+
+			local dir = minetest.dir_to_facedir(placer:get_look_dir())
+			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())
+				return itemstack
+			end
+
+			if not minetest.registered_nodes[minetest.get_node(botpos).name].buildable_to then
+				return itemstack
+			end
+
+			minetest.set_node(pos, {name = name .. "_bottom", param2 = dir})
+			minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
+
+			if not minetest.setting_getbool("creative_mode") then
+				itemstack:take_item()
+			end
+			return itemstack
+		end,
 
 		on_destruct = function(pos)
 			destruct_bed(pos, 1)
@@ -96,9 +115,10 @@ function beds.register_bed(name, def)
 				return false
 			end
 			node.param2 = new_param2
-			minetest.swap_node(pos, node)
-			minetest.remove_node(p)
-			minetest.set_node(newp, {name = node.name:gsub("%_bottom", "_top"), param2 = new_param2})
+			-- do not remove_node here - it will trigger destroy_bed()
+			minetest.set_node(p, {name = "air"})
+			minetest.set_node(pos, node)
+			minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
 			return true
 		end,
 	})
diff --git a/mods/beds/spawns.lua b/mods/beds/spawns.lua
index 14ec75b..f3980a7 100644
--- a/mods/beds/spawns.lua
+++ b/mods/beds/spawns.lua
@@ -18,8 +18,8 @@ function beds.read_spawns()
 		repeat
 			local x = input:read("*n")
 			if x == nil then
-            			break
-            		end
+				break
+			end
 			local y = input:read("*n")
 			local z = input:read("*n")
 			local name = input:read("*l")
@@ -52,7 +52,10 @@ function beds.set_spawns()
 	for name,_ in pairs(beds.player) do
 		local player = minetest.get_player_by_name(name)
 		local p = player:getpos()
-		beds.spawn[name] = p
+		-- but don't change spawn location if borrowing a bed
+		if not minetest.is_protected(p, name) then
+			beds.spawn[name] = p
+		end
 	end
 	beds.save_spawns()
 end