From ec416df7945f85bdb6fc50369b7049e52d96e791 Mon Sep 17 00:00:00 2001 From: hdastwb Date: Fri, 19 Jul 2013 01:36:55 -0400 Subject: [PATCH] added support for 6d facedir for all tube components, changed autoplace.lua to follow tubes.connect_sides rather than having each component coded individually, and added support for placing deployers and node breakers facing vertically --- autocrafter.lua | 3 +- autoplace.lua | 406 ++++++++++++++++++--------------------------- compat.lua | 12 +- deployer.lua | 143 ++++++++++++++-- item_transport.lua | 129 ++++++++++---- node_breaker.lua | 165 ++++++++++++++---- tubes.lua | 5 + 7 files changed, 530 insertions(+), 333 deletions(-) diff --git a/autocrafter.lua b/autocrafter.lua index 77a0160..8cca0a5 100644 --- a/autocrafter.lua +++ b/autocrafter.lua @@ -52,7 +52,8 @@ minetest.register_node("pipeworks:autocrafter",{ local inv=meta:get_inventory() return inv:room_for_item("src",stack) end, - input_inventory="dst"}, + input_inventory="dst", + connect_sides={left=1, right=1, front=1, back=1, top=1, bottom=1}}, on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", diff --git a/autoplace.lua b/autoplace.lua index a15d598..640c709 100644 --- a/autoplace.lua +++ b/autoplace.lua @@ -1,3 +1,78 @@ +--define the functions from https://github.com/minetest/minetest/pull/834 while waiting for the devs to notice it +local function dir_to_facedir(dir, is6d) + --account for y if requested + if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then + + --from above + if dir.y < 0 then + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 19 + else + return 13 + end + else + if dir.z < 0 then + return 10 + else + return 4 + end + end + + --from below + else + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 15 + else + return 17 + end + else + if dir.z < 0 then + return 6 + else + return 8 + end + end + end + + --otherwise, place horizontally + elseif math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 3 + else + return 1 + end + else + if dir.z < 0 then + return 2 + else + return 0 + end + end +end + +local function facedir_to_dir(facedir) + --a table of possible dirs + return ({{x=0, y=0, z=1}, + {x=1, y=0, z=0}, + {x=0, y=0, z=-1}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}, + {x=0, y=1, z=0}}) + + --indexed into by a table of correlating facedirs + [({[0]=1, 2, 3, 4, + 5, 2, 6, 4, + 6, 2, 5, 4, + 1, 5, 3, 6, + 1, 6, 3, 5, + 1, 4, 3, 2}) + + --indexed into by the facedir in question + [facedir]] +end + -- autorouting for pipes function pipe_scanforobjects(pos) @@ -55,257 +130,94 @@ function is_tube(nodename) end function tube_autoroute(pos) - local pxm=0 - local pxp=0 - local pym=0 - local pyp=0 - local pzm=0 - local pzp=0 - - local nxm = minetest.get_node({ x=pos.x-1, y=pos.y , z=pos.z }) - local nxp = minetest.get_node({ x=pos.x+1, y=pos.y , z=pos.z }) - local nym = minetest.get_node({ x=pos.x , y=pos.y-1, z=pos.z }) - local nyp = minetest.get_node({ x=pos.x , y=pos.y+1, z=pos.z }) - local nzm = minetest.get_node({ x=pos.x , y=pos.y , z=pos.z-1 }) - local nzp = minetest.get_node({ x=pos.x , y=pos.y , z=pos.z+1 }) - local nctr = minetest.get_node(pos) --- handle the tubes themselves - - if is_tube(nxm.name) then pxm=1 end - if is_tube(nxp.name) then pxp=1 end - if is_tube(nym.name) then pym=1 end - if is_tube(nyp.name) then pyp=1 end - if is_tube(nzm.name) then pzm=1 end - if is_tube(nzp.name) then pzp=1 end - --- handle regular filters - - if string.find(nxm.name, "pipeworks:filter") ~= nil - and nxm.param2 == 0 then - pxm=1 end - if string.find(nxp.name, "pipeworks:filter") ~= nil - and nxp.param2 == 2 then - pxp=1 end - if string.find(nzm.name, "pipeworks:filter") ~= nil - and nzm.param2 == 3 then - pzm=1 end - if string.find(nzp.name, "pipeworks:filter") ~= nil - and nzp.param2 == 1 then - pzp=1 end - --- handle mese filters - - if string.find(nxm.name, "pipeworks:mese_filter") ~= nil - and nxm.param2 == 0 then - pxm=1 end - if string.find(nxp.name, "pipeworks:mese_filter") ~= nil - and nxp.param2 == 2 then - pxp=1 end - if string.find(nzm.name, "pipeworks:mese_filter") ~= nil - and nzm.param2 == 3 then - pzm=1 end - if string.find(nzp.name, "pipeworks:mese_filter") ~= nil - and nzp.param2 == 1 then - pzp=1 end - --- handle deployers - - if string.find(nxm.name, "pipeworks:deployer_") ~= nil - and nxm.param2 == 1 then - pxm=1 end - if string.find(nxp.name, "pipeworks:deployer_") ~= nil - and nxp.param2 == 3 then - pxp=1 end - if string.find(nzm.name, "pipeworks:deployer_") ~= nil - and nzm.param2 == 0 then - pzm=1 end - if string.find(nzp.name, "pipeworks:deployer_") ~= nil - and nzp.param2 == 2 then - pzp=1 end - - if string.find(nxm.name, "technic:deployer_") ~= nil - and nxm.param2 == 1 then - pxm=1 end - if string.find(nxp.name, "technic:deployer_") ~= nil - and nxp.param2 == 3 then - pxp=1 end - if string.find(nzm.name, "technic:deployer_") ~= nil - and nzm.param2 == 0 then - pzm=1 end - if string.find(nzp.name, "technic:deployer_") ~= nil - and nzp.param2 == 2 then - pzp=1 end - ---node breakers - - if string.find(nxm.name, "pipeworks:nodebreaker_") ~= nil - and nxm.param2 == 1 then - pxm=1 end - if string.find(nxp.name, "pipeworks:nodebreaker_") ~= nil - and nxp.param2 == 3 then - pxp=1 end - if string.find(nzm.name, "pipeworks:nodebreaker_") ~= nil - and nzm.param2 == 0 then - pzm=1 end - if string.find(nzp.name, "pipeworks:nodebreaker_") ~= nil - and nzp.param2 == 2 then - pzp=1 end - - if string.find(nxm.name, "technic:nodebreaker_") ~= nil - and nxm.param2 == 1 then - pxm=1 end - if string.find(nxp.name, "technic:nodebreaker_") ~= nil - and nxp.param2 == 3 then - pxp=1 end - if string.find(nzm.name, "technic:nodebreaker_") ~= nil - and nzm.param2 == 0 then - pzm=1 end - if string.find(nzp.name, "technic:nodebreaker_") ~= nil - and nzp.param2 == 2 then - pzp=1 end - --- autocrafter - - if string.find(nxm.name, "pipeworks:autocrafter") ~= nil then pxm = 1 end - if string.find(nxp.name, "pipeworks:autocrafter") ~= nil then pxp = 1 end - if string.find(nym.name, "pipeworks:autocrafter") ~= nil then pym = 1 end - if string.find(nyp.name, "pipeworks:autocrafter") ~= nil then pyp = 1 end - if string.find(nzm.name, "pipeworks:autocrafter") ~= nil then pzm = 1 end - if string.find(nzp.name, "pipeworks:autocrafter") ~= nil then pzp = 1 end - ---chests - - -- check for left/right connects - - if string.find(nxm.name, "default:chest") ~= nil - and (nxm.param2 == 0 or nxm.param2 == 2) then - pxm=1 end - if string.find(nxp.name, "default:chest") ~= nil - and (nxp.param2 == 0 or nxp.param2 == 2) then - pxp=1 end - - if string.find(nzm.name, "default:chest") ~= nil - and (nzm.param2 == 1 or nzm.param2 == 3) then - pzm=1 end - if string.find(nzp.name, "default:chest") ~= nil - and (nzp.param2 == 1 or nzp.param2 == 3) then - pzp=1 end - - -- check for backside connects - - if string.find(nxm.name, "default:chest") ~= nil - and nxm.param2 == 1 then - pxm = 1 end - - if string.find(nxp.name, "default:chest") ~= nil - and nxp.param2 == 3 then - pxp = 1 end - - if string.find(nzm.name, "default:chest") ~= nil - and nzm.param2 == 0 then - pzm = 1 end - - if string.find(nzp.name, "default:chest") ~= nil - and nzp.param2 == 2 then - pzp = 1 end - - -- check for top/bottom connections - - if string.find(nym.name, "default:chest") ~= nil then pym = 1 end - if string.find(nyp.name, "default:chest") ~= nil then pyp = 1 end - - -- does not scan for the front side of the node. - ---locked chests - - -- check for left/right connects - - if string.find(nxm.name, "default:chest_locked") ~= nil - and (nxm.param2 == 0 or nxm.param2 == 2) then - pxm=1 end - if string.find(nxp.name, "default:chest_locked") ~= nil - and (nxp.param2 == 0 or nxp.param2 == 2) then - pxp=1 end - - if string.find(nzm.name, "default:chest_locked") ~= nil - and (nzm.param2 == 1 or nzm.param2 == 3) then - pzm=1 end - if string.find(nzp.name, "default:chest_locked") ~= nil - and (nzp.param2 == 1 or nzp.param2 == 3) then - pzp=1 end - - -- check for backside connects - - if string.find(nxm.name, "default:chest_locked") ~= nil - and nxm.param2 == 1 then - pxm = 1 end - - if string.find(nxp.name, "default:chest_locked") ~= nil - and nxp.param2 == 3 then - pxp = 1 end - - if string.find(nzm.name, "default:chest_locked") ~= nil - and nzm.param2 == 0 then - pzm = 1 end - - if string.find(nzp.name, "default:chest_locked") ~= nil - and nzp.param2 == 2 then - pzp = 1 end - - -- check for top/bottom connections - - if string.find(nym.name, "default:chest_locked") ~= nil then pym = 1 end - if string.find(nyp.name, "default:chest_locked") ~= nil then pyp = 1 end - - -- does not scan for the front side of the node. - ---furnaces - - -- check for left/right connects - - if string.find(nxm.name, "default:furnace") ~= nil - and (nxm.param2 == 0 or nxm.param2 == 2) then - pxm=1 end - if string.find(nxp.name, "default:furnace") ~= nil - and (nxp.param2 == 0 or nxp.param2 == 2) then - pxp=1 end - - if string.find(nzm.name, "default:furnace") ~= nil - and (nzm.param2 == 1 or nzm.param2 == 3) then - pzm=1 end - if string.find(nzp.name, "default:furnace") ~= nil - and (nzp.param2 == 1 or nzp.param2 == 3) then - pzp=1 end - - -- check for backside connects - - if string.find(nxm.name, "default:furnace") ~= nil - and nxm.param2 == 1 then - pxm = 1 end - - if string.find(nxp.name, "default:furnace") ~= nil - and nxp.param2 == 3 then - pxp = 1 end - - if string.find(nzm.name, "default:furnace") ~= nil - and nzm.param2 == 0 then - pzm = 1 end - - if string.find(nzp.name, "default:furnace") ~= nil - and nzp.param2 == 2 then - pzp = 1 end - - -- check for bottom connection - - if string.find(nyp.name, "default:furnace") ~= nil then pyp = 1 end - - -- does not scan for the front or top side of the node. - +--a function for determining which side of the node we are on + local function nodeside(node, tubedir) + + --get a vector pointing back + local backdir = facedir_to_dir(node.param2) + + --check whether the vector is equivalent to the tube direction; if it is, the tube's on the backside + if backdir.x == tubedir.x and backdir.y == tubedir.y and backdir.z == tubedir.z then + return "back" + end + + --check whether the vector is antiparallel with the tube direction; that indicates the front + if backdir.x == -tubedir.x and backdir.y == -tubedir.y and backdir.z == -tubedir.z then + return "front" + end + + --facedir is defined in terms of the top-bottom axis of the node; we'll take advantage of that + local topdir = ({[0]={x=0, y=1, z=0}, + {x=0, y=0, z=1}, + {x=0, y=0, z=-1}, + {x=1, y=0, z=0}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}})[math.floor(node.param2/4)] + + --is this the top? + if topdir.x == tubedir.x and topdir.y == tubedir.y and topdir.z == tubedir.z then + return "top" + end + + --or the bottom? + if topdir.x == -tubedir.x and topdir.y == -tubedir.y and topdir.z == -tubedir.z then + return "bottom" + end + + --we shall apply some maths to obtain the right-facing vector + local rightdir = {x=topdir.y*backdir.z - backdir.y*topdir.z, + y=topdir.z*backdir.x - backdir.z*topdir.x, + z=topdir.x*backdir.y - backdir.x*topdir.y} + + --is this the right side? + if rightdir.x == tubedir.x and rightdir.y == tubedir.y and rightdir.z == tubedir.z then + return "right" + end + + --or the left? + if rightdir.x == -tubedir.x and rightdir.y == -tubedir.y and rightdir.z == -tubedir.z then + return "left" + end + + --we should be done by now; initiate panic mode + minetest.log("error", "nodeside has been confused by its parameters; see pipeworks autoplace.lua, line 382") + + end + +--a further function for determining whether we should extend a tube in a certain direction + local function surchar(dir) + + --get the node in that direction + local node = minetest.get_node{x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} + + --and its tube table + local nodetube = minetest.registered_nodes[node.name].tube + + --choose a surround character + if nodetube and nodetube.connect_sides + and nodetube.connect_sides[nodeside(node, {x=-dir.x, y=-dir.y, z=-dir.z})] then + return '1' + else + return '0' + end + + end + +--keep track of the tube surroundings + local nsurround = "" + +--look in each direction + nsurround = nsurround..surchar{x=-1, y=0, z=0} + nsurround = nsurround..surchar{x=1, y=0, z=0} + nsurround = nsurround..surchar{x=0, y=-1, z=0} + nsurround = nsurround..surchar{x=0, y=1, z=0} + nsurround = nsurround..surchar{x=0, y=0, z=-1} + nsurround = nsurround..surchar{x=0, y=0, z=1} + -- Apply the final routing decisions to the existing tube (if any) - nsurround = pxm..pxp..pym..pyp..pzm..pzp if is_tube(nctr.name) then local meta=minetest.get_meta(pos) local meta0=meta:to_table() diff --git a/compat.lua b/compat.lua index 6113815..3bfeec1 100644 --- a/compat.lua +++ b/compat.lua @@ -32,7 +32,8 @@ furnace=clone_node("default:furnace") return 0 end end, - input_inventory="dst"} + input_inventory="dst", + connect_sides={left=1, right=1, back=1, bottom=1}} furnace.after_place_node= function(pos) tube_scanforobjects(pos) end @@ -65,7 +66,8 @@ furnace=clone_node("default:furnace_active") return 0 end end, - input_inventory="dst"} + input_inventory="dst", + connect_sides={left=1, right=1, back=1, bottom=1}} furnace.after_place_node= function(pos) tube_scanforobjects(pos) end @@ -88,7 +90,8 @@ chest=clone_node("default:chest") local inv=meta:get_inventory() return inv:room_for_item("main",stack) end, - input_inventory="main"} + input_inventory="main", + connect_sides={left=1, right=1, back=1, bottom=1, top=1}} chest.after_place_node = function(pos) tube_scanforobjects(pos) end @@ -111,7 +114,8 @@ chest_locked=clone_node("default:chest_locked") local meta=minetest.env:get_meta(pos) local inv=meta:get_inventory() return inv:room_for_item("main",stack) - end} + end, + connect_sides={left=1, right=1, back=1, bottom=1, top=1}} local old_after_place = minetest.registered_nodes["default:chest_locked"].after_place_node; chest_locked.after_place_node = function(pos, placer) tube_scanforobjects(pos) diff --git a/deployer.lua b/deployer.lua index c944331..01d4df2 100644 --- a/deployer.lua +++ b/deployer.lua @@ -9,6 +9,81 @@ end minetest.register_alias("technic:deployer_off", "pipeworks:deployer_off") minetest.register_alias("technic:deployer_on", "pipeworks:deployer_on") +--define the functions from https://github.com/minetest/minetest/pull/834 while waiting for the devs to notice it +local function dir_to_facedir(dir, is6d) + --account for y if requested + if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then + + --from above + if dir.y < 0 then + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 19 + else + return 13 + end + else + if dir.z < 0 then + return 10 + else + return 4 + end + end + + --from below + else + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 15 + else + return 17 + end + else + if dir.z < 0 then + return 6 + else + return 8 + end + end + end + + --otherwise, place horizontally + elseif math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 3 + else + return 1 + end + else + if dir.z < 0 then + return 2 + else + return 0 + end + end +end + +local function facedir_to_dir(facedir) + --a table of possible dirs + return ({{x=0, y=0, z=1}, + {x=1, y=0, z=0}, + {x=0, y=0, z=-1}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}, + {x=0, y=1, z=0}}) + + --indexed into by a table of correlating facedirs + [({[0]=1, 2, 3, 4, + 5, 2, 6, 4, + 6, 2, 5, 4, + 1, 5, 3, 6, + 1, 6, 3, 5, + 1, 4, 3, 2}) + + --indexed into by the facedir in question + [facedir]] +end + minetest.register_craft({ output = 'pipeworks:deployer_off 1', recipe = { @@ -32,18 +107,10 @@ deployer_on = function(pos, node) if node.name ~= "pipeworks:deployer_off" then return end - - local pos1 = {x=pos.x, y=pos.y, z=pos.z} - local pos2 = {x=pos.x, y=pos.y, z=pos.z} - if node.param2 == 3 then - pos1.x, pos2.x = pos1.x + 1, pos2.x + 2 - elseif node.param2 == 2 then - pos1.z, pos2.z = pos1.z + 1, pos2.z + 2 - elseif node.param2 == 1 then - pos1.x, pos2.x = pos1.x - 1, pos2.x - 2 - elseif node.param2 == 0 then - pos1.z, pos2.z = pos1.z - 1, pos2.z - 2 - end + + --locate the above and under positions + local dir = facedir_to_dir(node.param2) + local pos_under, pos_above = {x=pos.x - dir.x, y=pos.y - dir.y, z=pos.z - dir.z}, {x=pos.x - 2*dir.x, y=pos.y - 2*dir.y, z=pos.z - 2*dir.z} hacky_swap_node(pos,"pipeworks:deployer_on") nodeupdate(pos) @@ -51,13 +118,13 @@ deployer_on = function(pos, node) local inv = minetest.get_meta(pos):get_inventory() local invlist = inv:get_list("main") for i, stack in ipairs(invlist) do - if stack:get_name() ~= nil and stack:get_name() ~= "" and minetest.get_node(pos1).name == "air" then --obtain the first non-empty item slow + if stack:get_name() ~= nil and stack:get_name() ~= "" and minetest.get_node(pos_under).name == "air" then --obtain the first non-empty item slot local placer = { get_player_name = function() return "deployer" end, getpos = function() return pos end, get_player_control = function() return {jump=false,right=false,left=false,LMB=false,RMB=false,sneak=false,aux1=false,down=false,up=false} end, } - local stack2 = minetest.item_place(stack, placer, {type="node", under=pos1, above=pos2}) + local stack2 = minetest.item_place(stack, placer, {type="node", under=pos_under, above=pos_above}) if minetest.setting_getbool("creative_mode") and not minetest.get_modpath("unified_inventory") then --infinite stacks ahoy! stack2:take_item() end @@ -90,7 +157,8 @@ minetest.register_node("pipeworks:deployer_off", { local inv=meta:get_inventory() return inv:room_for_item("main",stack) end, - input_inventory="main"}, + input_inventory="main", + connect_sides={back=1}}, is_ground_content = true, paramtype2 = "facedir", groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2, mesecon = 2,tubedevice=1, tubedevice_receiver=1}, @@ -111,7 +179,26 @@ minetest.register_node("pipeworks:deployer_off", { local inv = meta:get_inventory() return inv:is_empty("main") end, - after_place_node = tube_scanforobjects, + after_place_node = function (pos, placer) + tube_scanforobjects(pos, placer) + local placer_pos = placer:getpos() + + --correct for the player's height + if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end + + --correct for 6d facedir + if placer_pos then + local dir = { + x = pos.x - placer_pos.x, + y = pos.y - placer_pos.y, + z = pos.z - placer_pos.z + } + local node = minetest.get_node(pos) + node.param2 = dir_to_facedir(dir, true) + minetest.set_node(pos, node) + minetest.log("action", "real (6d) facedir: " .. node.param2) + end + end, after_dig_node = tube_scanforobjects, }) @@ -130,7 +217,8 @@ minetest.register_node("pipeworks:deployer_on", { local inv=meta:get_inventory() return inv:room_for_item("main",stack) end, - input_inventory="main"}, + input_inventory="main", + connect_sides={back=1}}, is_ground_content = true, paramtype2 = "facedir", tubelike=1, @@ -152,6 +240,25 @@ minetest.register_node("pipeworks:deployer_on", { local inv = meta:get_inventory() return inv:is_empty("main") end, - after_place_node = tube_scanforobjects, + after_place_node = function (pos, placer) + tube_scanforobjects(pos, placer) + local placer_pos = placer:getpos() + + --correct for the player's height + if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end + + --correct for 6d facedir + if placer_pos then + local dir = { + x = pos.x - placer_pos.x, + y = pos.y - placer_pos.y, + z = pos.z - placer_pos.z + } + local node = minetest.get_node(pos) + node.param2 = dir_to_facedir(dir, true) + minetest.set_node(pos, node) + minetest.log("action", "real (6d) facedir: " .. node.param2) + end + end, after_dig_node = tube_scanforobjects, }) diff --git a/item_transport.lua b/item_transport.lua index 24fe5a9..f350ba0 100644 --- a/item_transport.lua +++ b/item_transport.lua @@ -2,6 +2,99 @@ modpath=minetest.get_modpath("pipeworks") dofile(modpath.."/compat.lua") +--define the functions from https://github.com/minetest/minetest/pull/834 while waiting for the devs to notice it +local function dir_to_facedir(dir, is6d) + --account for y if requested + if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then + + --from above + if dir.y < 0 then + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 19 + else + return 13 + end + else + if dir.z < 0 then + return 10 + else + return 4 + end + end + + --from below + else + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 15 + else + return 17 + end + else + if dir.z < 0 then + return 6 + else + return 8 + end + end + end + + --otherwise, place horizontally + elseif math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 3 + else + return 1 + end + else + if dir.z < 0 then + return 2 + else + return 0 + end + end +end + +local function facedir_to_dir(facedir) + --a table of possible dirs + return ({{x=0, y=0, z=1}, + {x=1, y=0, z=0}, + {x=0, y=0, z=-1}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}, + {x=0, y=1, z=0}}) + + --indexed into by a table of correlating facedirs + [({[0]=1, 2, 3, 4, + 5, 2, 6, 4, + 6, 2, 5, 4, + 1, 5, 3, 6, + 1, 6, 3, 5, + 1, 4, 3, 2}) + + --indexed into by the facedir in question + [facedir]] +end + +--and an extra function for getting the right-facing vector +local function facedir_to_right_dir(facedir) + + --find the other directions + local backdir = facedir_to_dir(facedir) + local topdir = ({[0]={x=0, y=1, z=0}, + {x=0, y=0, z=1}, + {x=0, y=0, z=-1}, + {x=1, y=0, z=0}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}})[math.floor(facedir/4)] + + --return a cross product + return {x=topdir.y*backdir.z - backdir.y*topdir.z, + y=topdir.z*backdir.x - backdir.z*topdir.x, + z=topdir.x*backdir.y - backdir.x*topdir.y} +end + minetest.register_craftitem("pipeworks:filter", { description = "Filter", stack_max = 99, @@ -39,24 +132,12 @@ minetest.register_node("pipeworks:filter", { mesecons={effector={action_on=function(pos,node) minetest.registered_nodes[node.name].on_punch(pos,node,nil) end}}, + tube={connect_sides={right=1}}, on_punch = function (pos, node, puncher) local meta = minetest.get_meta(pos); local inv = meta:get_inventory() - local frompos - local dir - if node.param2==0 then - frompos={x=pos.x-1,y=pos.y,z=pos.z} - dir={x=1,y=0,z=0} - elseif node.param2==1 then - frompos={x=pos.x,y=pos.y,z=pos.z+1} - dir={x=0,y=0,z=-1} - elseif node.param2==2 then - frompos={x=pos.x+1,y=pos.y,z=pos.z} - dir={x=-1,y=0,z=0} - else - frompos={x=pos.x,y=pos.y,z=pos.z-1} - dir={x=0,y=0,z=1} - end + local dir = facedir_to_right_dir(node.param2) + local frompos = {x=pos.x - dir.x, y=pos.y - dir.y, z=pos.z - dir.z} local fromnode=minetest.get_node(frompos) local frominv if (not fromnode) or (not minetest.registered_nodes[fromnode.name]) or (not (minetest.registered_nodes[fromnode.name].tube and @@ -137,24 +218,12 @@ minetest.register_node("pipeworks:mese_filter", { mesecons={effector={action_on=function(pos,node) minetest.registered_nodes[node.name].on_punch(pos,node,nil) end}}, + tube={connect_sides={right=1}}, on_punch = function (pos, node, puncher) local meta = minetest.get_meta(pos); local inv = meta:get_inventory() - local frompos - local dir - if node.param2==0 then - frompos={x=pos.x-1,y=pos.y,z=pos.z} - dir={x=1,y=0,z=0} - elseif node.param2==1 then - frompos={x=pos.x,y=pos.y,z=pos.z+1} - dir={x=0,y=0,z=-1} - elseif node.param2==2 then - frompos={x=pos.x+1,y=pos.y,z=pos.z} - dir={x=-1,y=0,z=0} - else - frompos={x=pos.x,y=pos.y,z=pos.z-1} - dir={x=0,y=0,z=1} - end + local dir = facedir_to_right_dir(node.param2) + local frompos = {x=pos.x - dir.x, y=pos.y - dir.y, z=pos.z - dir.z} local fromnode=minetest.get_node(frompos) local frominv if not (minetest.registered_nodes[fromnode.name].tube and diff --git a/node_breaker.lua b/node_breaker.lua index bb77c54..f6be474 100644 --- a/node_breaker.lua +++ b/node_breaker.lua @@ -30,6 +30,82 @@ function hacky_swap_node(pos,name) meta:from_table(meta0) end +--define the functions from https://github.com/minetest/minetest/pull/834 while waiting for the devs to notice it +local function dir_to_facedir(dir, is6d) + --account for y if requested + if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then + + --from above + if dir.y < 0 then + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 19 + else + return 13 + end + else + if dir.z < 0 then + return 10 + else + return 4 + end + end + + --from below + else + if math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 15 + else + return 17 + end + else + if dir.z < 0 then + return 6 + else + return 8 + end + end + end + + --otherwise, place horizontally + elseif math.abs(dir.x) > math.abs(dir.z) then + if dir.x < 0 then + return 3 + else + return 1 + end + else + if dir.z < 0 then + return 2 + else + return 0 + end + end +end + +local function facedir_to_dir(facedir) + --a table of possible dirs + return ({{x=0, y=0, z=1}, + {x=1, y=0, z=0}, + {x=0, y=0, z=-1}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}, + {x=0, y=1, z=0}}) + + --indexed into by a table of correlating facedirs + [({[0]=1, 2, 3, 4, + 5, 2, 6, 4, + 6, 2, 5, 4, + 1, 5, 3, 6, + 1, 6, 3, 5, + 1, 4, 3, 2}) + + --indexed into by the facedir in question + [facedir]] +end + + node_breaker_on = function(pos, node) if node.name == "pipeworks:nodebreaker_off" then hacky_swap_node(pos,"pipeworks:nodebreaker_on") @@ -45,32 +121,15 @@ node_breaker_off = function(pos, node) end end -function break_node (pos, n_param) - local pos1 = {x=pos.x, y=pos.y, z=pos.z} - local pos2 = {x=pos.x, y=pos.y, z=pos.z} - - --param2 3=x+ 1=x- 2=z+ 0=z- - local x_velocity, z_velocity = 0, 0 - if n_param == 3 then - pos2.x = pos2.x + 1 - pos1.x = pos1.x - 1 - x_velocity = -1 - elseif n_param == 2 then - pos2.z = pos2.z + 1 - pos1.z = pos1.z - 1 - z_velocity = -1 - elseif n_param == 1 then - pos2.x = pos2.x - 1 - pos1.x = pos1.x + 1 - x_velocity = 1 - elseif n_param == 0 then - pos2.z = pos2.z - 1 - pos1.x = pos1.z + 1 - z_velocity = 1 - end - - local node = minetest.get_node(pos2) - if node.name == "air" or name == "ignore" then +function break_node (pos, facedir) + + --locate the outgoing velocity, front, and back of the node via facedir_to_dir + local vel = facedir_to_dir(facedir); + local front = {x=pos.x - vel.x, y=pos.y - vel.y, z=pos.z - vel.z} + local back = {x=pos.x + vel.x, y=pos.y + vel.y, z=pos.z + vel.z} + + local node = minetest.get_node(front) + if node.name == "air" or node.name == "ignore" then return nil elseif minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].liquidtype ~= "none" then return nil @@ -84,7 +143,7 @@ function break_node (pos, n_param) --check node to make sure it is diggable local def = ItemStack({name=node.name}):get_definition() - if #def ~= 0 and not def.diggable or (def.can_dig and not def.can_dig(pos2, digger)) then --node is not diggable + if #def ~= 0 and not def.diggable or (def.can_dig and not def.can_dig(front, digger)) then --node is not diggable return end @@ -93,16 +152,16 @@ function break_node (pos, n_param) for _, dropped_item in ipairs(drops) do local item1 = tube_item({x=pos.x, y=pos.y, z=pos.z}, dropped_item) item1:get_luaentity().start_pos = {x=pos.x, y=pos.y, z=pos.z} - item1:setvelocity({x=x_velocity, y=0, z=z_velocity}) + item1:setvelocity(vel) item1:setacceleration({x=0, y=0, z=0}) end - minetest.remove_node(pos2) + minetest.remove_node(front) --handle post-digging callback if def.after_dig_node then -- Copy pos and node because callback can modify them - local pos_copy = {x=pos2.x, y=pos2.y, z=pos2.z} + local pos_copy = {x=front.x, y=front.y, z=front.z} local node_copy = {name=node.name, param1=node.param1, param2=node.param2} def.after_dig_node(pos_copy, node_copy, oldmetadata, digger) end @@ -110,7 +169,7 @@ function break_node (pos, n_param) --run digging event callbacks for _, callback in ipairs(minetest.registered_on_dignodes) do -- Copy pos and node because callback can modify them - local pos_copy = {x=pos2.x, y=pos2.y, z=pos2.z} + local pos_copy = {x=front.x, y=front.y, z=front.z} local node_copy = {name=node.name, param1=node.param1, param2=node.param2} callback(pos_copy, node_copy, digger) end @@ -125,7 +184,27 @@ minetest.register_node("pipeworks:nodebreaker_off", { groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2, mesecon = 2,tubedevice=1}, mesecons= {effector={action_on=node_breaker_on, action_off=node_breaker_off}}, sounds = default.node_sound_stone_defaults(), - after_place_node = tube_scanforobjects, + tube = {connect_sides={back=1}}, + after_place_node = function (pos, placer) + tube_scanforobjects(pos, placer) + local placer_pos = placer:getpos() + + --correct for the player's height + if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end + + --correct for 6d facedir + if placer_pos then + local dir = { + x = pos.x - placer_pos.x, + y = pos.y - placer_pos.y, + z = pos.z - placer_pos.z + } + local node = minetest.get_node(pos) + node.param2 = dir_to_facedir(dir, true) + minetest.set_node(pos, node) + minetest.log("action", "real (6d) facedir: " .. node.param2) + end + end, after_dig_node = tube_scanforobjects, }) @@ -138,6 +217,26 @@ minetest.register_node("pipeworks:nodebreaker_on", { paramtype2 = "facedir", groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2, mesecon = 2,tubedevice=1,not_in_creative_inventory=1}, sounds = default.node_sound_stone_defaults(), - after_place_node = tube_scanforobjects, + tube = {connect_sides={back=1}}, + after_place_node = function (pos, placer) + tube_scanforobjects(pos, placer) + local placer_pos = placer:getpos() + + --correct for the player's height + if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end + + --correct for 6d facedir + if placer_pos then + local dir = { + x = pos.x - placer_pos.x, + y = pos.y - placer_pos.y, + z = pos.z - placer_pos.z + } + local node = minetest.get_node(pos) + node.param2 = dir_to_facedir(dir, true) + minetest.set_node(pos, node) + minetest.log("action", "real (6d) facedir: " .. node.param2) + end + end, after_dig_node = tube_scanforobjects, }) diff --git a/tubes.lua b/tubes.lua index d38cf29..787001d 100644 --- a/tubes.lua +++ b/tubes.lua @@ -180,6 +180,7 @@ for zp = 0, 1 do stack_max = 99, drop = name.."_000000", tubelike=1, + tube = {connect_sides={front=1, back=1, left=1, right=1, top=1, bottom=1}}, on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_int("tubelike",1) @@ -210,6 +211,10 @@ for zp = 0, 1 do for group,val in pairs(value) do nodedef.groups[group]=val end + elseif key=="tube" then + for key,val in pairs(value) do + nodedef.tube[key]=val + end elseif type(value)=="table" then nodedef[key]=pipeworks_replace_name(value,"#id",tname) elseif type(value)=="string" then