Rotate optics and doors from NodeCore with ease.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.3 KiB

local minetest, vector, nodecore, include
= minetest, vector, nodecore, include
local hud = include("hud")
local rotate = include("rotate")
local utility = include("utility")
-- TODO: Add crosshair indicators for rotating around edges.
-- TODO: Register only the nodes that should be rotatable.
-- TODO: Replace `on_rightclick` of intended nodes.
-- TODO: Add some more comments.
-- Distance at which we want to rotate by "pushing" on an edge.
local EDGE_DISTANCE = 1.5 / 16 -- 1.5 texels (at 16² texture resolution)
local rotating_state = {}
nodecore.register_playerstep({
label = "extended rotating update",
action = function(player, player_data)
local name = player:get_player_name()
local state = {}; rotating_state[name] = state
local pointed_thing = player_data.raycast()
if (not pointed_thing) or pointed_thing.type ~= "node" then return nil end
state.pos = pointed_thing.under
state.node = minetest.get_node(state.pos)
if not rotate.is_rotatable(state.node) then return end
if vector.equals(pointed_thing.above, pointed_thing.under) then return end
state.face = pointed_thing.above - pointed_thing.under
local edge, distance = utility.find_closest_edge(state.node, pointed_thing)
if edge and distance > EDGE_DISTANCE then
state.axis = state.face
state.mode = "face"
else
state.axis = state.face:cross(edge):normalize():round()
state.mode = "edge"
end
state.invert = player:get_player_control().sneak
hud.update_player_hud(player, state)
end,
})
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
rotating_state[name] = nil
end)
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
if not minetest.is_player(puncher) then return end
local name = puncher:get_player_name()
local state = rotating_state[name]
if not state then return end
-- Make sure we're still the same node that we raycasted in `playerstep`.
if not vector.equals(pos, state.pos) then return end
if node.name ~= state.node.name or node.param2 ~= state.node.param2 then return end
local degrees = state.invert and 90 or -90
rotate.rotate_node(state.pos, state.node, state.axis, degrees)
end)