diff --git a/mods/drawers/api.lua b/mods/drawers/api.lua index c1153eb5..807b75dd 100755 --- a/mods/drawers/api.lua +++ b/mods/drawers/api.lua @@ -251,7 +251,26 @@ function drawers.register_drawer(name, def) def.on_metadata_inventory_put = drawers.add_drawer_upgrade def.on_metadata_inventory_take = drawers.remove_drawer_upgrade - if minetest.get_modpath 'screwdriver' and screwdriver then def.on_rotate = def.on_rotate or screwdriver.disallow end + if minetest.get_modpath 'screwdriver' and screwdriver then + def.on_rotate = function(pos, node, user, mode, new_param2) + if mode ~= screwdriver.ROTATE_FACE then + return false + end + + local rotation = node.param2 % 32 + local color_bits = node.param2 - rotation + local new_rotation = (rotation + 1) % 4 + + node.param2 = color_bits + new_rotation + minetest.swap_node(pos, node) + + -- Respawn visuals with new rotation + drawers.remove_visuals(pos) + drawers.spawn_visuals(pos) + + return true + end + end if minetest.get_modpath 'pipeworks' and pipeworks then def.groups.tubedevice = 1 @@ -411,4 +430,4 @@ function drawers.register_drawer_upgrade(name, def) } template = name end -end +end \ No newline at end of file diff --git a/mods/sbz_pipeworks/autoplace_tubes.lua b/mods/sbz_pipeworks/autoplace_tubes.lua index 56de3e91..6145c287 100644 --- a/mods/sbz_pipeworks/autoplace_tubes.lua +++ b/mods/sbz_pipeworks/autoplace_tubes.lua @@ -31,9 +31,58 @@ local function nodeside(node, tubedir) local right = vector.dot(rightdir, tubedir) if right == 1 then return "right" - else + elseif right == -1 then return "left" end + + -- Fallback with a warning for inapplicable values + -- (e.g. one that produces a direction not aligned to any axis). + core.log("warning", "[pipeworks] nodeside: unexpected tubedir, defaulting to left. " .. + "node.param2=" .. tostring(node.param2) .. + " tubedir=" .. minetest.pos_to_string(tubedir)) + return "left" +end + +-- Convert camera yaw and pitch to the nearest facedir param2 value. + +-- Degrees start at 0 facing North, increasing while turning counter-clockwise (if looking down from above): +-- 0 = looking toward +Z (North) +-- π/2 = looking toward -X (West) +-- π = looking toward -Z (South) +-- 3π/2 = looking toward +X (East) +-- +local function look_to_facedir(yaw, pitch) + -- Vertical placement threshold (directionality favors yaw, but allows pitch) + local limit = math.pi * 0.40 -- ≈ 72° + + -- Looking up means node faces down + if pitch > limit then + return 0 + elseif pitch < -limit then + return 20 + end + + -- Round yaw to nearest 90° sector. + -- Normalise to [0, 2π) first so the modulo is well-defined. + yaw = yaw % (2 * math.pi) + local sector = math.floor(yaw / (math.pi / 2) + 0.5) % 4 + + -- Map sector index to facedir param2. + -- Sector 0 (yaw ≈ 0): looking toward +Z (North) | param2 as 2 would make node face North + -- Sector 1 (yaw ≈ π/2): looking toward -X (West) | param2 as 1 would make node face West + -- Sector 2 (yaw ≈ π): looking toward -Z (South) | param2 as 0 would make node face South + -- Sector 3 (yaw ≈ 3π/2):looking toward +X (East) | param2 as 3 would make node face East + + -- Use opposite angles instead so that it faces camera + return ({ [0] = 0, 3, 2, 1 })[sector] -- node mirrors (not matches) camera angle when placed +end + +local function yaw_to_4dir(yaw) + yaw = yaw % (2 * math.pi) + local sector = math.floor(yaw / (math.pi / 2) + 0.5) % 4 + + -- Map yaw sectors to 4dir param2 + return ({ [0] = 0, 3, 2, 1 })[sector] end local vts = { 0, 3, 1, 4, 2, 5 } @@ -100,13 +149,37 @@ local function tube_autoroute(pos) end function pipeworks.scan_for_tube_objects(pos) - for side = 0, 6 do + for side = 1, 6 do tube_autoroute(vector.add(pos, pipeworks.directions.side_to_dir(side))) end end -function pipeworks.after_place(pos) - pipeworks.scan_for_tube_objects(pos) +-- FIX: after_place previously saved original_param2, called scan_for_tube_objects +-- (which skipped autorouting pos itself), then restored original_param2 — but that +-- restoration was misguided because: +-- 1. The placed node IS a tube and SHOULD be autorouted like any other tube. +-- 2. Neighbours were updated while seeing whatever param2 the node happened to +-- have at placement time, which may not match the final autorouted state. + +function pipeworks.after_place(pos, placer) + if placer and placer.get_look_horizontal then + local node = minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + + local yaw = placer:get_look_horizontal() + local pitch = placer.get_look_vertical and placer:get_look_vertical() or 0 + + if def.paramtype2 == "4dir" then + node.param2 = yaw_to_4dir(yaw) + elseif def.paramtype2 == "facedir" then + node.param2 = look_to_facedir(yaw, pitch) + end + + minetest.swap_node(pos, node) + end + + tube_autoroute(pos) + pipeworks.scan_for_tube_objects(pos) end function pipeworks.after_dig(pos) diff --git a/mods/sbz_pipeworks/basic_tubes.lua b/mods/sbz_pipeworks/basic_tubes.lua index 06a35fa4..cce005a9 100644 --- a/mods/sbz_pipeworks/basic_tubes.lua +++ b/mods/sbz_pipeworks/basic_tubes.lua @@ -192,7 +192,9 @@ minetest.register_node('pipeworks:one_way_tube', { end, priority = 75, -- Higher than normal tubes, but lower than receivers }, - after_place_node = pipeworks.after_place, + after_place_node = function(pos) + pipeworks.scan_for_tube_objects(pos) + end, after_dig_node = pipeworks.after_dig, on_rotate = pipeworks.on_rotate, }) diff --git a/mods/sbz_pipeworks/wielder.lua b/mods/sbz_pipeworks/wielder.lua index d5d7d194..2b7da399 100644 --- a/mods/sbz_pipeworks/wielder.lua +++ b/mods/sbz_pipeworks/wielder.lua @@ -150,6 +150,12 @@ function pipeworks.register_wielder(def) -- Rotate to face the clicked block local dir = vector.subtract(pointed_thing.above, pointed_thing.under) + + -- Flip direction if this wielder should face away + if def.place_facing == "away" then + dir = vector.multiply(dir, -1) + end + local param2 = minetest.dir_to_facedir(dir, true) local node = minetest.get_node(pos) @@ -229,6 +235,7 @@ function pipeworks.register_wielder(def) }) end +-- Nodebreaker faces away from clicked block side when placed. pipeworks.register_wielder { name = 'pipeworks:nodebreaker', description = S 'Node Breaker', @@ -241,6 +248,7 @@ pipeworks.register_wielder { 'nodebreaker_front.png', }, connect_sides = { top = 1, bottom = 1, left = 1, right = 1, back = 1 }, + place_facing = "away", wield_inv = { name = 'pick', width = 1, height = 1 }, wield_hand = true, eject_drops = true, @@ -291,6 +299,7 @@ pipeworks.register_wielder { cost = 20, } +-- Deployer faces away from clicked block side when placed. pipeworks.register_wielder { name = 'pipeworks:deployer', description = S 'Deployer', @@ -302,6 +311,7 @@ pipeworks.register_wielder { 'deployer_back.png', 'deployer_front.png', }, + place_facing = "away", wield_inv = { name = 'main', width = 3, height = 3 }, connect_sides = { back = 1 }, action = function(fakeplayer, pointed) @@ -321,6 +331,7 @@ pipeworks.register_wielder { cost = 20, } +-- Puncher faces toward clicked block side when placed. pipeworks.register_wielder { name = 'pipeworks:puncher', description = S 'Puncher', @@ -332,6 +343,7 @@ pipeworks.register_wielder { 'interactor_bottom.png', -- back 'interactor_top.png', -- front }, + place_facing = "toward", wield_inv = { name = 'pick', width = 1, height = 1 }, connect_sides = { top = 1, bottom = 1, left = 1, right = 1, back = 1 }, wield_hand = true, @@ -403,4 +415,4 @@ do { I, I, I }, }, }) -end +end \ No newline at end of file diff --git a/mods/sbz_resources/storinators.lua b/mods/sbz_resources/storinators.lua index 9d57640f..9ce61be3 100644 --- a/mods/sbz_resources/storinators.lua +++ b/mods/sbz_resources/storinators.lua @@ -105,6 +105,27 @@ local function register_storinator(added_name, def) def_copy.on_metadata_inventory_move = update_node_texture def_copy.info_extra = def_copy.slots .. " Slots" + def_copy.on_rotate = function(pos, node, user, mode, new_param2) + -- Only handle the 'Face' rotation (Left Click) + if mode ~= screwdriver.ROTATE_FACE then + return false + end + + -- 1. Isolate the rotation (first 5 bits) and the color (everything else) + local rotation = node.param2 % 32 + local color_bits = node.param2 - rotation + + -- 2. Manually cycle through the 4 horizontal directions (0, 1, 2, 3) + -- This makes it behave exactly like the Crystal Grower + local new_rotation = (rotation + 1) % 4 + + -- 3. Re-combine and apply + node.param2 = color_bits + new_rotation + minetest.swap_node(pos, node) + + return true -- Tells the screwdriver we handled it! + end + local dropname = "sbz_resources:storinator" if #added_name ~= 0 then dropname = dropname .. "_" .. added_name @@ -303,4 +324,4 @@ minetest.register_craft({ { "sbz_resources:matter_plate", "sbz_resources:simple_circuit", "sbz_resources:matter_plate" }, { "sbz_resources:retaining_circuit", "sbz_resources:matter_plate", "sbz_resources:retaining_circuit" } } -}) +}) \ No newline at end of file