Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use game/mod-provided screwdriver handlers if present #368

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion technic/mod.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name = technic
depends = pipeworks, technic_worldgen, basic_materials
optional_depends = mcl_core, mcl_sounds, default, bucket, mesecons, mesecons_mvps, digilines, digiline_remote, unified_inventory, dye, craftguide, i3, mtt, vizlib, moreores, mcl_buckets, mcl_explosions, mcl_craftguide
optional_depends = mcl_core, mcl_sounds, default, bucket, mesecons, mesecons_mvps, digilines, digiline_remote, unified_inventory, dye, craftguide, i3, mtt, vizlib, moreores, mcl_buckets, mcl_explosions, mcl_craftguide, screwdriver
118 changes: 83 additions & 35 deletions technic/tools/sonic_screwdriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,43 @@ local sonic_screwdriver_max_charge = 15000
local S = technic.getter
local mat = technic.materials

-- screwdriver handler code reused from minetest/minetest_game screwdriver @a9ac480
local ROTATE_FACE = 1
local ROTATE_AXIS = 2

local function nextrange(x, max)
x = x + 1
if x > max then
x = 0
local screwdriver = screwdriver or nil
if not screwdriver then
local function nextrange(x, max)
x = x + 1
if x > max then
x = 0
end
return x
end
return x

-- Simple and hacky rotation script, assumed facedir
local function simple_rotate(pos, node, mode)
local rotationPart = node.param2 % 32 -- get first 4 bits
local preservePart = node.param2 - rotationPart

local axisdir = math.floor(rotationPart / 4)
local rotation = rotationPart - axisdir * 4
if mode == screwdriver.ROTATE_FACE then
rotationPart = axisdir * 4 + nextrange(rotation, 3)
elseif mode == screwdriver.ROTATE_AXIS then
rotationPart = nextrange(axisdir, 5) * 4
end

return preservePart + rotationPart
end

-- local use only
screwdriver = {
ROTATE_FACE = 1,
ROTATE_AXIS = 2,

rotate = setmetatable({}, {
__index = function ()
return simple_rotate
end
})
}
end

-- Handles rotation
Expand All @@ -21,45 +48,66 @@ local function screwdriver_handler(itemstack, user, pointed_thing, mode)
return
end

if technic.get_RE_charge(itemstack) < 100 then
return itemstack
end

local pos = pointed_thing.under
local player_name = user and user:get_player_name() or ""

if minetest.is_protected(pos, user:get_player_name()) then
minetest.record_protection_violation(pos, user:get_player_name())
if minetest.is_protected(pos, player_name) then
minetest.record_protection_violation(pos, player_name)
return
end

local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
if not ndef or ndef.paramtype2 ~= "facedir" or
(ndef.drawtype == "nodebox" and
ndef.node_box.type ~= "fixed") or
node.param2 == nil then
return
if not ndef then
return itemstack
end
-- can we rotate this paramtype2?
local fn = screwdriver.rotate[ndef.paramtype2]
if not fn and not ndef.on_rotate then
return itemstack
end

local should_rotate = true
local new_param2
if fn then
new_param2 = fn(pos, node, mode)
if not new_param2 then
-- rotation refused
return itemstack
end
else
new_param2 = node.param2
end

-- Node provides a handler, so let the handler decide instead if the node can be rotated
-- contrary to the default screwdriver, do not check for can_dig, to allow rotating machines with CLU's in them
-- this is consistent with the previous sonic screwdriver

if not technic.use_RE_charge(itemstack, 100) then
return
if ndef.on_rotate then
-- Copy pos and node because callback can modify it
local result = ndef.on_rotate(vector.new(pos),
{name = node.name, param1 = node.param1, param2 = node.param2},
user, mode, new_param2)
if result == false then -- Disallow rotation
return itemstack
elseif result == true then
should_rotate = false
end
elseif ndef.on_rotate == false then
return itemstack
end

minetest.sound_play("technic_sonic_screwdriver", {pos = pos, gain = 0.3, max_hear_distance = 10}, true)

-- Set param2
local rotationPart = node.param2 % 32 -- get first 4 bits
local preservePart = node.param2 - rotationPart

local axisdir = math.floor(rotationPart / 4)
local rotation = rotationPart - axisdir * 4
if mode == ROTATE_FACE then
rotationPart = axisdir * 4 + nextrange(rotation, 3)
elseif mode == ROTATE_AXIS then
rotationPart = nextrange(axisdir, 5) * 4
if should_rotate and new_param2 ~= node.param2 then
node.param2 = new_param2
minetest.swap_node(pos, node)
minetest.check_for_falling(pos)
minetest.sound_play("technic_sonic_screwdriver", {pos = pos, gain = 0.3, max_hear_distance = 10}, true)
end

node.param2 = preservePart + rotationPart
minetest.swap_node(pos, node)
technic.use_RE_charge(itemstack, 100)

return itemstack
end
Expand All @@ -69,10 +117,10 @@ technic.register_power_tool("technic:sonic_screwdriver", {
inventory_image = "technic_sonic_screwdriver.png",
max_charge = sonic_screwdriver_max_charge,
on_use = function(itemstack, user, pointed_thing)
return screwdriver_handler(itemstack, user, pointed_thing, ROTATE_FACE)
return screwdriver_handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE)
end,
on_place = function(itemstack, user, pointed_thing)
return screwdriver_handler(itemstack, user, pointed_thing, ROTATE_AXIS)
return screwdriver_handler(itemstack, user, pointed_thing, screwdriver.ROTATE_AXIS)
end,
})

Expand Down
Loading