mirror of
https://gitlab.com/deetmit/mesecons_x.git
synced 2024-09-12 00:06:44 +02:00
600 lines
16 KiB
Lua
600 lines
16 KiB
Lua
|
|
function is_in_selection(sel,p)
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
if pos[1] == nil then return false end
|
|
if pos[2] == nil then return false end
|
|
|
|
local xmax = math.max(pos[1].x, pos[2].x)
|
|
local xmin = math.min(pos[1].x, pos[2].x)
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
local zmax = math.max(pos[1].z, pos[2].z)
|
|
local zmin = math.min(pos[1].z, pos[2].z)
|
|
|
|
local x = p.x
|
|
local y = p.y
|
|
local z = p.z
|
|
|
|
if (xmin<=p.x) and (p.x<=xmax) and
|
|
(ymin<=p.y) and (p.y<=ymax) and
|
|
(zmin<=p.z) and (p.z<=zmax) then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function is_in_layer(sel,p)
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
if (p.y > ymax) or (p.y< ymin) then return false end
|
|
return true
|
|
|
|
end
|
|
|
|
function is_in_tube(sel,p)
|
|
if is_in_selection(sel,p) then return false end
|
|
if not is_in_layer(sel,p) then return false end
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
local xmax = math.max(pos[1].x, pos[2].x)
|
|
local xmin = math.min(pos[1].x, pos[2].x)
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
local zmax = math.max(pos[1].z, pos[2].z)
|
|
local zmin = math.min(pos[1].z, pos[2].z)
|
|
|
|
local x = p.x
|
|
local y = p.y
|
|
local z = p.z
|
|
|
|
if (xmin <=x ) and (x<=xmax) then return true end
|
|
if (zmin <=z) and (z<=zmax) then return true end
|
|
return false
|
|
|
|
end
|
|
--[[
|
|
function is_in_wings(sel,p)
|
|
if is_in_selection(sel,p) then return false end
|
|
if not is_in_layer(sel,p) then return false end
|
|
if is_in_tube(sel,p) then return false end
|
|
return true
|
|
end
|
|
]]--
|
|
|
|
|
|
function front_wall_tube(sel,p)
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
local xmax = math.max(pos[1].x, pos[2].x)
|
|
local xmin = math.min(pos[1].x, pos[2].x)
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
local zmax = math.max(pos[1].z, pos[2].z)
|
|
local zmin = math.min(pos[1].z, pos[2].z)
|
|
|
|
local x = p.x
|
|
local y = p.y
|
|
local z = p.z
|
|
|
|
local new_sel = {}
|
|
local new_pos1 = vector.new(pos[1])
|
|
local new_pos2 = vector.new(pos[2])
|
|
local direction = {}
|
|
|
|
|
|
if (xmin<=x) and (x<=xmax) then
|
|
if (z > zmax) then
|
|
direction.x = 0
|
|
direction.y = 0
|
|
direction.z = 1
|
|
|
|
new_pos1.z = zmax
|
|
new_pos2.z = zmax
|
|
else
|
|
direction.x = 0
|
|
direction.y = 0
|
|
direction.z = -1
|
|
|
|
new_pos1.z = zmin
|
|
new_pos2.z = zmin
|
|
end
|
|
end
|
|
if (zmin<=z) and (z<=zmax) then
|
|
if( x > xmax) then
|
|
direction.x = 1
|
|
direction.y = 0
|
|
direction.z = 0
|
|
|
|
new_pos1.x = xmax
|
|
new_pos2.x = xmax
|
|
else
|
|
direction.x = -1
|
|
direction.y = 0
|
|
direction.z = 0
|
|
|
|
new_pos1.x = xmin
|
|
new_pos2.x = xmin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
new_sel.pos1 = new_pos1
|
|
new_sel.pos2 = new_pos2
|
|
|
|
return new_sel,direction
|
|
end
|
|
|
|
function tunel_direction(sel,pos)
|
|
local wall,dir = front_wall_tube(sel,pos)
|
|
return dir
|
|
end
|
|
|
|
function tunel_front_wall(sel,pos)
|
|
local wall,dir = front_wall_tube(sel,pos)
|
|
return wall
|
|
end
|
|
|
|
|
|
|
|
|
|
function is_dir_vertical(direction)
|
|
if direction.z ~= 0 then return true end
|
|
return false
|
|
end
|
|
|
|
function is_look_vertical(rad)
|
|
local dir = radians_to_direction_looking_forward(rad)
|
|
return is_dir_vertical(dir)
|
|
end
|
|
|
|
--[[
|
|
function is_dir_horizontal(direction)
|
|
if direction.x ~= then return true end
|
|
return false
|
|
end
|
|
]]--
|
|
|
|
function front_wall_by_direction(sel,direction)
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
local xmax = math.max(pos[1].x, pos[2].x)
|
|
local xmin = math.min(pos[1].x, pos[2].x)
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
local zmax = math.max(pos[1].z, pos[2].z)
|
|
local zmin = math.min(pos[1].z, pos[2].z)
|
|
|
|
|
|
local new_sel = {}
|
|
local new_pos1 = vector.new(pos[1])
|
|
local new_pos2 = vector.new(pos[2])
|
|
|
|
if direction.x == 1 then
|
|
new_pos1.x = xmax
|
|
new_pos2.x = xmax
|
|
end
|
|
if direction.x == -1 then
|
|
new_pos1.x = xmin
|
|
new_pos2.x = xmin
|
|
end
|
|
if direction.z == 1 then
|
|
new_pos1.z = zmax
|
|
new_pos2.z = zmax
|
|
end
|
|
if direction.z == -1 then
|
|
new_pos1.z = zmin
|
|
new_pos2.z = zmin
|
|
end
|
|
if direction.y == 1 then
|
|
new_pos1.y = ymax
|
|
new_pos2.y = ymax
|
|
end
|
|
if direction.y == -1 then
|
|
new_pos1.y = ymin
|
|
new_pos2.y = ymin
|
|
end
|
|
|
|
new_sel.pos1 = new_pos1
|
|
new_sel.pos2 = new_pos2
|
|
|
|
return new_sel
|
|
end
|
|
--[[
|
|
function get_wing_cords(sel,p)
|
|
local zero = {x =0,z=0}
|
|
local cord
|
|
if is_in_selection(sel,p) then return zero end
|
|
if not is_in_layer(sel,p) then return zero end
|
|
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
local xmax = math.max(pos[1].x, pos[2].x)
|
|
local xmin = math.min(pos[1].x, pos[2].x)
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
local zmax = math.max(pos[1].z, pos[2].z)
|
|
local zmin = math.min(pos[1].z, pos[2].z)
|
|
|
|
local x = p.x
|
|
local y = p.y
|
|
local z = p.z
|
|
|
|
if (x>xmax) and (z>zmax) then
|
|
cord = { x = 1, z = 1}
|
|
end
|
|
if (x<xmin) and (z>zmax) then
|
|
cord = {x = -1 , z = 1}
|
|
end
|
|
if (z<zmin) and (x>xmax) then
|
|
cord = { x = 1 , z = -1 }
|
|
end
|
|
if (z < zmin) and (x < xmin) then
|
|
cord = { x -1 ,z = -1 }
|
|
end
|
|
|
|
return cord
|
|
end
|
|
]]--
|
|
--[[
|
|
function front_wall_wing(sel,p,rad)
|
|
local cord = get_wing_cords(sel,p)
|
|
|
|
local wall_dir
|
|
wall_dir.y = 0
|
|
|
|
if cord.x == 1 and cord.z == 1 then
|
|
if is_look_vertical(rad) then
|
|
wall_dir = {x=1,z=0}
|
|
else
|
|
wall_dir = {x=0,z=1}
|
|
end
|
|
end
|
|
|
|
if cord.x == -1 and cord.z == 1 then
|
|
if is_look_vertical(rad) then
|
|
wall_dir = {x=-1,z=0}
|
|
else
|
|
wall_dir = {x=0,z=1}
|
|
end
|
|
end
|
|
|
|
if cord.x == 1 and cord.z == -1 then
|
|
if is_look_vertical(rad) then
|
|
wall_dir = {x=1,z=0}
|
|
else
|
|
wall_dir = {x=0,z=-1}
|
|
end
|
|
end
|
|
|
|
if cord.x == -1 and cord.z == -1 then
|
|
if is_look_vertical(rad) then
|
|
wall_dir = {x=-1,z=0}
|
|
else
|
|
wall_dir = {x=0,z=-1}
|
|
end
|
|
end
|
|
|
|
local wall = front_wall_by_direction(wall_dir)
|
|
|
|
return wall,wall_dir
|
|
end
|
|
|
|
]]--
|
|
function distance_to_selection(sel,p,direction)
|
|
local dist = 0
|
|
local pos = {}
|
|
pos[1] = sel.pos1
|
|
pos[2] = sel.pos2
|
|
|
|
if not is_in_layer(sel,p) then return dist end
|
|
|
|
--local direction = tunel_direction(sel,p)
|
|
|
|
|
|
local xmax = math.max(pos[1].x, pos[2].x)
|
|
local xmin = math.min(pos[1].x, pos[2].x)
|
|
|
|
local ymax = math.max(pos[1].y, pos[2].y)
|
|
local ymin = math.min(pos[1].y, pos[2].y)
|
|
|
|
local zmax = math.max(pos[1].z, pos[2].z)
|
|
local zmin = math.min(pos[1].z, pos[2].z)
|
|
|
|
if direction.x ~= 0 then
|
|
if direction.x == 1 then
|
|
dist = math.abs(p.x - xmax)
|
|
elseif direction.x == -1 then
|
|
dist = math.abs(xmin-p.x)
|
|
end
|
|
|
|
elseif direction.z ~= 0 then
|
|
if direction.z == 1 then
|
|
dist = math.abs(p.z - zmax)
|
|
elseif direction.z == -1 then
|
|
dist = math.abs(zmin - p.z)
|
|
end
|
|
|
|
end
|
|
|
|
return dist + 1
|
|
|
|
end
|
|
|
|
--[[
|
|
function direction_to_pins(direction)
|
|
local pin = {0,0,0,0}
|
|
if direction.x == -1 then
|
|
pin[1] = 1
|
|
end
|
|
if direction.x == 1 then
|
|
pin[3] = 1
|
|
end
|
|
if direction.z == 1 then
|
|
pin[2] = 1
|
|
end
|
|
if direction.z == -1 then
|
|
pin[4] == 1
|
|
end
|
|
return pin
|
|
end
|
|
]]--
|
|
function direction_to_pin(direction)
|
|
if direction.x == -1 then
|
|
return 1
|
|
end
|
|
if direction.x == 1 then
|
|
return 3
|
|
end
|
|
if direction.z == 1 then
|
|
return 2
|
|
end
|
|
if direction.z == -1 then
|
|
return 4
|
|
end
|
|
end
|
|
|
|
|
|
function pos_to_connect(wall,direction)
|
|
local list = {}
|
|
iterate_selection(wall.pos1,wall.pos2, function(pos)
|
|
local pins = get_pins_from_pos(pos)
|
|
local dpin = direction_to_pin(direction)
|
|
if pins[dpin] == 1 then
|
|
table.insert(list,pos)
|
|
end
|
|
end)
|
|
return list
|
|
end
|
|
|
|
function _is_block_type(pos,direction)
|
|
local node = minetest.get_node(pos)
|
|
local name = node.name
|
|
|
|
if name == "air" then
|
|
return "buildable"
|
|
end
|
|
|
|
if name == "mesecons_insulated:insulated_off" or
|
|
name == "mesecons_insulated:insulated_on" then
|
|
|
|
local param2 = node.param2
|
|
local pin = direction_to_pin(direction)
|
|
|
|
if (param2==0 or param2==2) and (pin==2 or pin==4) then
|
|
return "buildable"
|
|
end
|
|
if (param2==1 or param2==3) and (pin==1 or pin==3) then
|
|
return "buildable"
|
|
end
|
|
return "last"
|
|
end
|
|
|
|
|
|
local pos_pins = get_pins_from_pos(pos)
|
|
local dir_pin = flip_pin(direction_to_pin(direction))
|
|
if pos_pins[dir_pin] ==1 then
|
|
return "last"
|
|
end
|
|
return "cancel"
|
|
end
|
|
|
|
|
|
function is_block_type(pos,direction)
|
|
local res = _is_block_type(pos,direction)
|
|
local node = minetest.get_node(pos)
|
|
local name = node.name
|
|
|
|
|
|
return res
|
|
end
|
|
|
|
|
|
function is_block_cancel(pos,direction)
|
|
if is_block_type(pos,direction) == "cancel" then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function is_block_last(pos,direction)
|
|
if is_block_type(pos,direction) == "last" then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function is_block_buildable(pos,direction)
|
|
if is_block_type(pos,direction) == "buildable" then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
|
|
|
|
function _can_build_wire(pos,direction,size)
|
|
local current = { x=pos.x , y =pos.y, z=pos.z}
|
|
|
|
local flag = false
|
|
for i=1,size,1 do
|
|
|
|
if is_block_cancel(current,direction) then
|
|
return false
|
|
end
|
|
if is_block_last(current,direction) then
|
|
return true
|
|
end
|
|
|
|
current = vector.add(current,direction)
|
|
end
|
|
return flag
|
|
end
|
|
|
|
function can_build_wire(pos,direction,size)
|
|
return _can_build_wire(pos,direction,size)
|
|
end
|
|
|
|
|
|
function add_wire(pos,direction)
|
|
local node = minetest.get_node(pos)
|
|
local name = node.name
|
|
|
|
if name == "air" then
|
|
local pins = get_pins_from_pos(pos)
|
|
local dpin = direction_to_pin(direction)
|
|
|
|
pins[dpin] = 1
|
|
pins[flip_pin(dpin)] = 1
|
|
|
|
local nnode = get_node_from_pins(pins)
|
|
|
|
--minetest.set_node(pos,nnode)
|
|
mesecons_autotools.set_node(pos,nnode,"add_wire")
|
|
else
|
|
local nnode = { name = "mesecons_extrawires:crossover_off" }
|
|
--minetest.set_node(pos, nnode)
|
|
mesecons_autotools.set_node(pos,nnode,"add_wire")
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
--[[ not used
|
|
function add_last_wire(pos,direction)
|
|
local pins = get_pins_from_pos(pos)
|
|
local dpin = direction_to_pin(direction)
|
|
|
|
pins[flip_pin(dpin)] = 1
|
|
|
|
local node = get_node_from_pins(pins)
|
|
|
|
minetest.set_node(pos,node)
|
|
|
|
end
|
|
]]--
|
|
|
|
function build_wire_inside(pos,direction,size)
|
|
local current = { x=pos.x , y =pos.y, z=pos.z}
|
|
|
|
if not can_build_wire(pos,direction,size) then return end
|
|
|
|
for i=1,size,1 do
|
|
if is_block_cancel(current,direction) then
|
|
return
|
|
elseif is_block_buildable(current,direction) then
|
|
add_wire(current,direction)
|
|
elseif is_block_last(current,direction) then
|
|
break
|
|
end
|
|
current = vector.add(current,direction)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
function create_wires_inside_selection(sel,wall,direction)
|
|
local size = size_by_direction(sel.pos1,sel.pos2,direction)
|
|
local back_direction = vector.multiply(direction,-1)
|
|
|
|
|
|
iterate_selection(wall.pos1,wall.pos2,function(pos)
|
|
build_wire_inside(pos,back_direction,size)
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
function create_bundle_straight_wire(sel,pos)
|
|
local pos1 = sel.pos1
|
|
local pos2 = sel.pos2
|
|
|
|
|
|
if not is_in_tube(sel,pos) then return false end
|
|
|
|
|
|
local wall,direction = front_wall_tube(sel,pos)
|
|
|
|
|
|
local distance = distance_to_selection(sel,pos,direction)
|
|
|
|
if is_one_block(pos1,pos2) or
|
|
is_empty_selection(pos1,pos2) or
|
|
is_tower_selection(pos1,pos2) then
|
|
|
|
iterate_selection(sel.pos1, sel.pos2, function(pos)
|
|
create_straight_wire_n(pos,direction,distance)
|
|
end)
|
|
else
|
|
|
|
|
|
|
|
create_wires_inside_selection(sel,wall,direction)
|
|
|
|
|
|
local wire_list = pos_to_connect(wall,direction)
|
|
iterate_list(wire_list,function(pos)
|
|
create_straight_wire_n(pos,direction,distance)
|
|
end)
|
|
|
|
end
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|