From efb81d188e8dc9f8c4862baab0b5be5fb53c21ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1niel=20Juh=C3=A1sz?= <juhdanad@gmail.com>
Date: Mon, 27 Feb 2017 10:50:54 +0100
Subject: [PATCH] Correct rotation of attached nodes, and rotate colored nodes

---
 mods/screwdriver/init.lua | 46 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/mods/screwdriver/init.lua b/mods/screwdriver/init.lua
index 94964605..95514094 100644
--- a/mods/screwdriver/init.lua
+++ b/mods/screwdriver/init.lua
@@ -11,6 +11,19 @@ screwdriver.rotate_simple = function(pos, node, user, mode, new_param2)
 	end
 end
 
+-- For attached wallmounted nodes: returns true if rotation is valid
+-- simplified version of minetest:builtin/game/falling.lua#L148.
+local function check_attached_node(pos, rotation)
+	local d = minetest.wallmounted_to_dir(rotation)
+	local p2 = vector.add(pos, d)
+	local n = minetest.get_node(p2).name
+	local def2 = minetest.registered_nodes[n]
+	if def2 and not def2.walkable then
+		return false
+	end
+	return true
+end
+
 screwdriver.rotate = {}
 
 local facedir_tbl = {
@@ -32,18 +45,39 @@ local facedir_tbl = {
 	},
 }
 
-screwdriver.rotate.facedir = function(node, mode)
-	return facedir_tbl[mode][node.param2]
+screwdriver.rotate.facedir = function(pos, node, mode)
+	local rotation = node.param2 % 32 -- get first 5 bits
+	local other = node.param2 - rotation
+	rotation = facedir_tbl[mode][rotation] or 0
+	return rotation + other
 end
 
+screwdriver.rotate.colorfacedir = screwdriver.rotate.facedir
+
 local wallmounted_tbl = {
 	[screwdriver.ROTATE_FACE] = {[2] = 5, [3] = 4, [4] = 2, [5] = 3, [1] = 0, [0] = 1},
 	[screwdriver.ROTATE_AXIS] = {[2] = 5, [3] = 4, [4] = 2, [5] = 1, [1] = 0, [0] = 3}
 }
-screwdriver.rotate.wallmounted = function(node, mode)
-	return wallmounted_tbl[mode][node.param2]
+
+screwdriver.rotate.wallmounted = function(pos, node, mode)
+	local rotation = node.param2 % 8 -- get first 3 bits
+	local other = node.param2 - rotation
+	rotation = wallmounted_tbl[mode][rotation] or 0
+	if minetest.get_item_group(node.name, "attached_node") ~= 0 then
+		-- find an acceptable orientation
+		for i = 1, 5 do
+			if not check_attached_node(pos, rotation) then
+				rotation = wallmounted_tbl[mode][rotation] or 0
+			else
+				break
+			end
+		end
+	end
+	return rotation + other
 end
 
+screwdriver.rotate.colorwallmounted = screwdriver.rotate.wallmounted
+
 -- Handles rotation
 screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses)
 	if pointed_thing.type ~= "node" then
@@ -66,7 +100,7 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses)
 	end
 
 	local should_rotate = true
-	local new_param2 = fn(node, mode)
+	local new_param2 = fn(pos, node, mode)
 
 	-- Node provides a handler, so let the handler decide instead if the node can be rotated
 	if ndef and ndef.on_rotate then
@@ -80,7 +114,7 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses)
 			should_rotate = false
 		end
 	else
-		if not ndef or not ndef.paramtype2 == "facedir" or
+		if not ndef or
 				ndef.on_rotate == false or
 				(ndef.drawtype == "nodebox" and
 				(ndef.node_box and ndef.node_box.type ~= "fixed")) or
-- 
GitLab