@@ -3,16 +3,43 @@ local sonic_screwdriver_max_charge = 15000
3
3
local S = technic .getter
4
4
local mat = technic .materials
5
5
6
- -- screwdriver handler code reused from minetest/minetest_game screwdriver @a9ac480
7
- local ROTATE_FACE = 1
8
- local ROTATE_AXIS = 2
9
-
10
- local function nextrange ( x , max )
11
- x = x + 1
12
- if x > max then
13
- x = 0
6
+ local screwdriver = screwdriver or nil
7
+ if not screwdriver then
8
+ local function nextrange ( x , max )
9
+ x = x + 1
10
+ if x > max then
11
+ x = 0
12
+ end
13
+ return x
14
14
end
15
- return x
15
+
16
+ -- Simple and hacky rotation script, assumed facedir
17
+ local function simple_rotate (pos , node , mode )
18
+ local rotationPart = node .param2 % 32 -- get first 4 bits
19
+ local preservePart = node .param2 - rotationPart
20
+
21
+ local axisdir = math.floor (rotationPart / 4 )
22
+ local rotation = rotationPart - axisdir * 4
23
+ if mode == screwdriver .ROTATE_FACE then
24
+ rotationPart = axisdir * 4 + nextrange (rotation , 3 )
25
+ elseif mode == screwdriver .ROTATE_AXIS then
26
+ rotationPart = nextrange (axisdir , 5 ) * 4
27
+ end
28
+
29
+ return preservePart + rotationPart
30
+ end
31
+
32
+ -- local use only
33
+ screwdriver = {
34
+ ROTATE_FACE = 1 ,
35
+ ROTATE_AXIS = 2 ,
36
+
37
+ rotate = setmetatable ({}, {
38
+ __index = function ()
39
+ return simple_rotate
40
+ end
41
+ })
42
+ }
16
43
end
17
44
18
45
-- Handles rotation
@@ -21,45 +48,66 @@ local function screwdriver_handler(itemstack, user, pointed_thing, mode)
21
48
return
22
49
end
23
50
51
+ if technic .get_RE_charge (itemstack ) < 100 then
52
+ return itemstack
53
+ end
54
+
24
55
local pos = pointed_thing .under
56
+ local player_name = user and user :get_player_name () or " "
25
57
26
- if minetest .is_protected (pos , user : get_player_name () ) then
27
- minetest .record_protection_violation (pos , user : get_player_name () )
58
+ if minetest .is_protected (pos , player_name ) then
59
+ minetest .record_protection_violation (pos , player_name )
28
60
return
29
61
end
30
62
31
63
local node = minetest .get_node (pos )
32
64
local ndef = minetest .registered_nodes [node .name ]
33
- if not ndef or ndef .paramtype2 ~= " facedir" or
34
- (ndef .drawtype == " nodebox" and
35
- ndef .node_box .type ~= " fixed" ) or
36
- node .param2 == nil then
37
- return
65
+ if not ndef then
66
+ return itemstack
67
+ end
68
+ -- can we rotate this paramtype2?
69
+ local fn = screwdriver .rotate [ndef .paramtype2 ]
70
+ if not fn and not ndef .on_rotate then
71
+ return itemstack
72
+ end
73
+
74
+ local should_rotate = true
75
+ local new_param2
76
+ if fn then
77
+ new_param2 = fn (pos , node , mode )
78
+ if not new_param2 then
79
+ -- rotation refused
80
+ return itemstack
81
+ end
82
+ else
83
+ new_param2 = node .param2
38
84
end
39
85
86
+ -- Node provides a handler, so let the handler decide instead if the node can be rotated
40
87
-- contrary to the default screwdriver, do not check for can_dig, to allow rotating machines with CLU's in them
41
88
-- this is consistent with the previous sonic screwdriver
42
-
43
- if not technic .use_RE_charge (itemstack , 100 ) then
44
- return
89
+ if ndef .on_rotate then
90
+ -- Copy pos and node because callback can modify it
91
+ local result = ndef .on_rotate (vector .new (pos ),
92
+ {name = node .name , param1 = node .param1 , param2 = node .param2 },
93
+ user , mode , new_param2 )
94
+ if result == false then -- Disallow rotation
95
+ return itemstack
96
+ elseif result == true then
97
+ should_rotate = false
98
+ end
99
+ elseif ndef .on_rotate == false then
100
+ return itemstack
45
101
end
46
102
47
- minetest .sound_play (" technic_sonic_screwdriver" , {pos = pos , gain = 0.3 , max_hear_distance = 10 }, true )
48
-
49
- -- Set param2
50
- local rotationPart = node .param2 % 32 -- get first 4 bits
51
- local preservePart = node .param2 - rotationPart
52
-
53
- local axisdir = math.floor (rotationPart / 4 )
54
- local rotation = rotationPart - axisdir * 4
55
- if mode == ROTATE_FACE then
56
- rotationPart = axisdir * 4 + nextrange (rotation , 3 )
57
- elseif mode == ROTATE_AXIS then
58
- rotationPart = nextrange (axisdir , 5 ) * 4
103
+ if should_rotate and new_param2 ~= node .param2 then
104
+ node .param2 = new_param2
105
+ minetest .swap_node (pos , node )
106
+ minetest .check_for_falling (pos )
107
+ minetest .sound_play (" technic_sonic_screwdriver" , {pos = pos , gain = 0.3 , max_hear_distance = 10 }, true )
59
108
end
60
109
61
- node .param2 = preservePart + rotationPart
62
- minetest .swap_node (pos , node )
110
+ technic .use_RE_charge (itemstack , 100 )
63
111
64
112
return itemstack
65
113
end
@@ -69,10 +117,10 @@ technic.register_power_tool("technic:sonic_screwdriver", {
69
117
inventory_image = " technic_sonic_screwdriver.png" ,
70
118
max_charge = sonic_screwdriver_max_charge ,
71
119
on_use = function (itemstack , user , pointed_thing )
72
- return screwdriver_handler (itemstack , user , pointed_thing , ROTATE_FACE )
120
+ return screwdriver_handler (itemstack , user , pointed_thing , screwdriver . ROTATE_FACE )
73
121
end ,
74
122
on_place = function (itemstack , user , pointed_thing )
75
- return screwdriver_handler (itemstack , user , pointed_thing , ROTATE_AXIS )
123
+ return screwdriver_handler (itemstack , user , pointed_thing , screwdriver . ROTATE_AXIS )
76
124
end ,
77
125
})
78
126
0 commit comments