mesecons_x/mesecons_autotools/tools/wire.lua
Deet Mit 68aadf9953 fix
2020-09-04 16:21:35 +02:00

446 lines
13 KiB
Lua

function get_node_from_pins(pins)
local t = "mesecons_extrawires:tjunction_off"
local c = "mesecons_extrawires:corner_off"
local w = "mesecons_insulated:insulated_off"
local a = "air"
local x = "mesecons_morewires:xjunction_off"
-- {left,up,right,down node_name, rotation}
local list = {
-- empty
{0,0,0,0,a,0},
-- wire
{1,0,1,0,w,0},
{0,1,0,1,w,1},
-- corner
{1,0,0,1,c,0},
{1,1,0,0,c,1},
{0,1,1,0,c,2},
{0,0,1,1,c,3},
-- tjunction
{1,0,1,1,t,0},
{1,1,0,1,t,1},
{1,1,1,0,t,2},
{0,1,1,1,t,3},
-- xjunction
{1,1,1,1,x,0},
-- starting wire
{1,0,0,0,w,0},
{0,1,0,0,w,1},
{0,0,1,0,w,0},
{0,0,0,1,w,1},
}
local node_name = "air"
local rotate = 0
for _,v in ipairs(list) do
if (pins[1] == v[1]) and
(pins[2] == v[2]) and
(pins[3] == v[3]) and
(pins[4] == v[4]) then
node_name = v[5]
rotate = v[6]
end
end
return { name = node_name, param2 = rotate }
end
function get_pins_from_pos(pos,type)
local node = minetest.get_node(pos)
local rs = {}
if type == "input" then
rs = mesecon.get_any_inputrules(node)
elseif type == "output" then
rs = mesecon.get_any_outputrules(node)
else
rs = mesecon.get_any_rules(node)
end
if rs == nil then
rs = {}
else
rs = mesecon.flattenrules (rs)
end
-- Filter only y=0
local list = {}
for _,v in pairs(rs) do
if v.y == 0 then
if v.x ~= 0 and v.z == 0 then
table.insert(list,v)
end
if v.z ~= 0 and v.x == 0 then
table.insert(list,v)
end
end
end
-- constructiong pin structure
local pins = {0,0,0,0}
for _,v in pairs(list) do
if v.x == 1 then pins[3] = 1 end
if v.x == -1 then pins[1] = 1 end
if v.z == 1 then pins[2] = 1 end
if v.z == -1 then pins[4] = 1 end
end
return pins
end
local function dir_to_inx(d)
if d.x == 1 then return 3 end
if d.x == -1 then return 1 end
if d.z == 1 then return 2 end
if d.z == -1 then return 4 end
return 1
end
function get_pin_from_direction(direction)
return dir_to_inx(direction)
end
local function neighbours_pins(pos)
local npins = {0,0,0,0}
for _,ix in ipairs({1,-1}) do
local shift = { x=ix,y=0,z=0 }
local neigh = vector.add(pos,shift)
local pins = get_pins_from_pos(neigh)
npins[ dir_to_inx( shift) ] = pins [ dir_to_inx( vector.multiply(shift,-1) ) ]
end
for _,iz in ipairs({1,-1}) do
local shift = { x=0,y=0,z=iz }
local neigh = vector.add(pos,shift)
local pins = get_pins_from_pos(neigh)
npins[ dir_to_inx( shift) ] = pins [ dir_to_inx( vector.multiply(shift,-1) ) ]
end
return npins
end
local function pins_and(pins1,pins2)
local pout = {}
for i=1,4,1 do
pout[i] = pins1[i] * pins2[i]
end
return pout
end
local function start_node(pos,direction)
local node = minetest.get_node(pos)
local name = node.name
-- Only wires changed
local list = {
"mesecons_insulated:insulated_off","mesecons_insulated:insulated_on",
"mesecons_extrawires:corner_off","mesecons_extrawires:corner_on",
"mesecons_extrawires:tjunction_off", "mesecons_extrawires:tjunction_on",
"air"
}
if not is_in_list(list,name) then return end
local npins = neighbours_pins(pos)
local mypins = get_pins_from_pos(pos)
local compins = pins_and(npins,mypins)
-- adding wire
if direction.x == 1 then
compins[3] = 1
end
if direction.x == -1 then
compins[1] = 1
end
if direction.z == 1 then
compins[2] = 1
end
if direction.z == -1 then
compins[4] = 1
end
--merge_wire(pos,direction)
local new_node = get_node_from_pins(compins)
--minetest.set_node(pos,new_node)
mesecons_autotools.set_node(pos,new_node,"start_node")
end
local function end_node(pos,direction)
--merge_wire(pos, vector.multiply(direction, -1))
start_node(pos, vector.multiply(direction,-1))
end
local function middle_node(pos, direction)
local node = minetest.get_node(pos)
local name = node.name
local param2 = node.param2
--minetest.set_node(pos,{name = "default:dirt"})
--if true then return end
if name ~= "mesecons_insulated:insulated_off" and
name ~= "mesecons_insulated:insulated_on" and
name ~= "air" then
return
end
-- do crossing
if name == "air" then
local prm2 = 0
if direction.z ~= 0 then
prm2 = 1
end
if direction.x ~= 0 then
prm2 = 0
end
--minetest.set_node(pos, { name ="mesecons_insulated:insulated_off", param2= 1 } )
mesecons_autotools.set_node(pos,
{name ="mesecons_insulated:insulated_off", param2= prm2 },
"middle_node")
else
-- if nothing to do
if (direction.x ~= 0 ) and
( param2 == 0 or param2 == 2 ) then
return
end
if (direction.z ~= 0 ) and
(param2 == 1 or param2 == 3 ) then
return
end
--minetest.set_node(pos,{ name ="mesecons_extrawires:crossover_off" } )
mesecons_autotools.set_node(pos,
{ name ="mesecons_extrawires:crossover_off" },
"middle_node")
end
end
function create_straight_wire_n(pos,direction,size)
local current = pos
-- first
start_node(current,direction)
current = vector.add(current,direction)
-- middle
for i = 2, size-1, 1 do
middle_node(current,direction)
current = vector.add(current,direction)
end
-- last
end_node(current,direction)
end
local function distance_taxi_metric(pos1,pos2)
local x1 = pos1.x
local x2 = pos2.x
local dx = math.abs(x2-x1)
local z1 = pos1.z
local z2 = pos2.z
local dz = math.abs(z2-z1)
return dz+dx+1
end
function create_straight_wire(pos1,pos2)
-- Check if straight line
if pos1.y ~= pos2.y then return end
if (pos1.x ~= pos2.x ) and (pos1.z ~= pos2.z) then return end
-- Compute direction
local direction = { x =0,y=0,z=0}
if pos1.x == pos2.x then
if pos1.z < pos2.z then
direction.z = 1
else
direction.z = -1
end
end
if pos1.z == pos2.z then
if pos1.x < pos2.x then
direction.x = 1
else
direction.x = -1
end
end
-- Compute size
local size = distance_taxi_metric(pos1,pos2)
create_straight_wire_n(pos1,direction,size)
return true
end
function hop_pos(pos,pin)
local new_pos = { x = pos.x, y = pos.y, z = pos.z }
if pin == 1 then
new_pos.x = pos.x - 1
end
if pin == 2 then
new_pos.z = pos.z + 1
end
if pin == 3 then
new_pos.x = pos.x + 1
end
if pin == 4 then
new_pos.z = pos.z -1
end
return new_pos
end
function flip_pin(pin)
if pin == 1 then return 3 end
if pin == 2 then return 4 end
if pin == 3 then return 1 end
if pin == 4 then return 2 end
end
-- TODO: refactor
function hop_pin(pin)
if pin == 1 then return 3 end
if pin == 2 then return 4 end
if pin == 3 then return 1 end
if pin == 4 then return 2 end
end
local function delete(p,pin)
local node = minetest.get_node(p)
local name = node.name
if name == "mesecons_insulated:insulated_off" or
name == "mesecons_insulated:insulated_on" or
name == "mesecons_extrawires:corner_off" or
name == "mesecons_extrawires:corner_on"
then
-- continue deleting
local node_pins = get_pins_from_pos(p)
-- not connected to anything
if node_pins[pin] == 0 then return end
node_pins[pin] = 0
for i=1,4,1 do
if node_pins[i] == 1 then
--minetest.set_node(p,{name="air"})
mesecons_autotools.set_node(p,{name="air"},"delete")
delete(hop_pos(p,i),hop_pin(i))
end
end
elseif name == "mesecons_extrawires:crossover_off" or
name == "mesecons_extrawires:crossover_on" or
name == "mesecons_extrawires:crossover_10" or
name == "mesecons_extrawires:crossover_01" then
-- continue deleting
local node_pins = get_pins_from_pos(p)
node_pins[pin] = 0
node_pins[hop_pin(pin)] = 0
local new_node = get_node_from_pins(node_pins)
-- minetest.set_node(p,new_node)
mesecons_autotools.set_node(p,new_node,"delete_crossover")
delete(hop_pos(p,hop_pin(pin)),pin)
elseif name == "mesecons_extrawires:tjunction_off" or
name == "mesecons_extrawires:tjunction_on" or
name == "mesecons_morewires:xjunction_off" or
name == "mesecons_morewires:xjunction_on" then
-- end of wire
local node_pins = get_pins_from_pos(p)
-- not connected to anything
if node_pins[pin] == 0 then return end
node_pins[pin] = 0
local new_node = get_node_from_pins(node_pins)
--minetest.set_node(p,new_node)
mesecons_autotools.set_node(p,new_node,"delete_end")
else
-- do nothing (other blocks)
end
end
function delete_node(pos)
local node = minetest.get_node(pos)
local pins = get_pins_from_pos(pos)
--minetest.set_node(pos,{name="air"})
mesecons_autotools.set_node(pos,{name="air"},"delete")
for i=1,4,1 do
if pins[i] == 1 then
delete(hop_pos(pos,i),hop_pin(i))
end
end
end