mesecons_x/mesecons_autowire/auto_move.lua
2020-07-18 13:41:25 +02:00

628 lines
16 KiB
Lua

mesecons_automove = {}
local function put_node(pos,node)
minetest.set_node(pos,node)
-- mesecon.on_placenode(pos,node)
end
local function put_node_activate(pos,node)
minetest.set_node(pos,node)
mesecon.on_placenode(pos,node)
end
local function sort_xz(p1,p2)
if (p1.x < p2.x ) then
return p1,p2
elseif( p1.x > p2.x ) then
return p2,p1
else
-- p1.x == p2.x
if( p1.z < p2.z ) then
return p1,p2
else
return p2,p1
end
end
return p1,p2
end
function update_selection()
if(mesecons_automove.pos1e ~= nil) then
mesecons_automove.pos1e:remove()
mesecons_automove.pos1e = nil
end
if(mesecons_automove.pos2e ~= nil) then
mesecons_automove.pos2e:remove()
mesecons_automove.pos2e = nil
end
if(mesecons_automove.pos1 ~= nil ) then
mesecons_automove.pos1e =
minetest.add_entity(mesecons_automove.pos1,"mesecons_automove:pos1")
end
if(mesecons_automove.pos2 ~= nil ) then
mesecons_automove.pos2e =
minetest.add_entity(mesecons_automove.pos2,"mesecons_automove:pos2")
end
end
--[[
function update_selection()
if( mesecons_automove.pos1 == nil ) or (mesecons_automove.pos2 == nil ) then return end
if( mesecons_automove.pos1 ~= nil ) and (mesecons_automove.pos1e ~= nil ) then
mesecons_automove.pos1e:remove()
mesecons_automove.pos1e = minetest.add_entity(mesecons_automove.pos1,"mesecons_automove:pos1")
end
if( mesecons_automove.pos2 ~= nil ) and (mesecons_automove.pos2e ~= nil ) then
mesecons_automove.pos2e:remove()
mesecons_automove.pos2e = minetest.add_entity(mesecons_automove.pos2,"mesecons_automove:pos2")
end
end
]]--
function radians_to_vectors(rad)
local pi = math.pi
if (rad>=0) and (rad<=pi/4) or (rad<=2*pi) and (rad>=(3/2+1/4)*pi) then
return {left = {x=-1,z=0},right = { x=1, z = 0 } }
elseif (rad >= 1/4*pi) and (rad <= (1/2+1/4)*pi) then
return { left = {x = 0 ,z=-1}, right = { x = 0, z = 1 } }
elseif (rad >= (1-1/4)*pi ) and (rad <= (3/2-1/4)*pi ) then
return { left = { x = 1, z =0 }, right = { x = -1, z = 0 } }
else
return { left = { z =1, x = 0 } , right = { z = -1 , x = 0 }}
end
end
local function get_front_wall(pos1,pos2,direction)
local y = pos1.y -- p1.y == p2.y
local x,z
local d= direction
if d.x == -1 then
local m = math.min(pos1.x,pos2.x)-1 -- aoutside the selection
return {
pos1 = { x = m, y = y, z = pos1.z},
pos2 = { x = m, y = y, z = pos2.z},
}
elseif d.x == 1 then
local m = math.max(pos1.x,pos2.x)+1 -- aoutside the selection
return {
pos1 = { x = m, y = y, z = pos1.z},
pos2 = { x = m, y = y, z = pos2.z},
}
elseif d.z == -1 then
local m = math.min(pos1.z,pos2.z)-1 -- aoutside the selection
return {
pos1 = { x = pos1.x, y = y, z = m},
pos2 = { x = pos2.x, y = y, z = m},
}
else
--if d.z == 1 then
local m = math.max(pos1.z,pos2.z)+1 -- aoutside the selection
return {
pos1 = { x = pos1.x, y = y, z = m},
pos2 = { x = pos2.x, y = y, z = m},
}
end
end
local function get_back_wall(p1,p2,direction)
local pos1,pos2 = sort_xz(p1,p2)
local y = pos1.y -- p1.y == p2.y
local x,z
local d= direction
if d.x == 1 then
local m = math.min(pos1.x,pos2.x) -- aoutside the selection
return {
pos1 = { x = m, y = y, z = pos1.z},
pos2 = { x = m, y = y, z = pos2.z},
}
elseif d.x == -1 then
local m = math.max(pos1.x,pos2.x) -- aoutside the selection
return {
pos1 = { x = m, y = y, z = pos1.z},
pos2 = { x = m, y = y, z = pos2.z},
}
elseif d.z == 1 then
local m = math.min(pos1.z,pos2.z) -- aoutside the selection
return {
pos1 = { x = pos1.x, y = y, z = m},
pos2 = { x = pos2.x, y = y, z = m},
}
else
--if d.z == 1 then
local m = math.max(pos1.z,pos2.z) -- aoutside the selection
return {
pos1 = { x = pos1.x, y = y, z = m},
pos2 = { x = pos2.x, y = y, z = m},
}
end
end
local function have_output(pos,direction)
local neight_pos = { x = pos.x -direction.x, y = pos.y, z = pos.z - direction.z }
local neight_pin = get_pins_sticky(neight_pos)
local pin = get_pins_sticky(pos)
-- check if connected with each other
if(direction.x == 1 ) then
if not (( pin.l == 1 ) and (neight_pin.r == 1 ) ) then return false end
elseif( direction.x == -1 ) then
if not ( (pin.r == 1) and (neight_pin.l == 1) ) then return false end
elseif( direction.z == 1 ) then
if not (( pin.d == 1 ) and (neight_pin.u == 1 ) ) then return false end
else
if not ((pin.u == 1) and (neight_pin.d == 1 )) then return false end
end
print("debug.pin="..dump(pos))
if( pin.u == 1 ) and (direction.z == -1 ) then return true end
if( pin.d == 1 ) and (direction.z == 1 ) then return true end
if( pin.l == 1 ) and (direction.x == 1 ) then return true end
if( pin.r == 1 ) and (direction.x == -1 ) then return true end
return false
end
local function get_outputs(wall,direction)
local pos1 = wall.pos1
local pos2 = wall.pos2
local list = {}
if pos1.x == pos2.x then
local f = math.min(pos1.z, pos2.z)
local t = math.max(pos1.z, pos2.z)
for i=f,t do
local posi = { y = pos1.y, x = pos1.x , z = i }
if( have_output( posi , direction ) == true ) then
table.insert(list,posi)
end
end
else
-- pos1.z == pos2.z
local f = math.min(pos1.x, pos2.x)
local t = math.max(pos1.x, pos2.x)
for i=f,t do
local posi = { y = pos1.y, z = pos1.z , x = i }
if( have_output( posi , direction ) == true ) then
table.insert(list,posi)
end
end
end
print("DEBUG.list = "..dump(list))
return list
end
-- callback fun(pos)
local function foreach_wall(wall,fun)
local pos1 = wall.pos1
local pos2 = wall.pos2
if pos1.x == pos2.x then
local f = math.min(pos1.z, pos2.z)
local t = math.max(pos1.z, pos2.z)
for i=f,t do
local posi = { y = pos1.y, x = pos1.x , z = i }
fun(posi)
end
else
-- pos1.z == pos2.z
local f = math.min(pos1.x, pos2.x)
local t = math.max(pos1.x, pos2.x)
for i=f,t do
local posi = { y = pos1.y, z = pos1.z , x = i }
fun(posi)
end
end
end
local function move_single_node(pos,direction)
local node = minetest.get_node(pos)
minetest.set_node(pos, { name = "air" } )
local new_pos = { x = pos.x + direction.x,y = pos.y ,z = pos.z + direction.z }
put_node(new_pos,node)
end
local function move_nodes(direction)
local pos1 = mesecons_automove.pos1
local pos2 = mesecons_automove.pos2
-- needed later
local back_wall = get_back_wall(pos1,pos2,direction)
local outputs = get_outputs(back_wall,direction)
-- removes front wall
local wall = get_front_wall(pos1,pos2,direction)
foreach_wall(wall, function(pos) minetest.set_node(pos,{name="air"}) end )
-- moves each "colum" from the front to end
local xf, xt, xd , zf, zt, zd
if( direction.x == 1 ) then
xt = math.min(pos1.x, pos2.x)
xf = math.max(pos1.x, pos2.x)
zf = math.min(pos1.z, pos2.z)
zt = math.max(pos1.z, pos2.z)
xd = -1
zd = 1
elseif(direction.x == -1 ) then
xf = math.min(pos1.x, pos2.x)
xt = math.max(pos1.x, pos2.x)
zf = math.min(pos1.z, pos2.z)
zt = math.max(pos1.z, pos2.z)
xd = 1
zd = 1
elseif(direction.z == 1 ) then
xf = math.min(pos1.x, pos2.x)
xt = math.max(pos1.x, pos2.x)
zt = math.min(pos1.z, pos2.z)
zf = math.max(pos1.z, pos2.z)
xd = 1
zd = -1
else -- direction.z == -1
xf = math.min(pos1.x, pos2.x)
xt = math.max(pos1.x, pos2.x)
zf = math.min(pos1.z, pos2.z)
zt = math.max(pos1.z, pos2.z)
xd = 1
zd = 1
end
for ix = xf,xt,xd do
for iz = zf,zt,zd do
-- print("move("..ix..","..iz..")")
local current = { x = ix, y=pos1.y , z = iz }
move_single_node(current,direction)
end
end
-- adding wires at the end
print("debug: back_wall =" ..dump(back_wall) .. ", outputs = ".. dump(outputs))
for _,p in ipairs(outputs) do
if( direction.z == 0 ) then
-- x direction
put_node_activate(p,{name = "mesecons_insulated:insulated_off", param2 = 0 } )
else
-- z direction
put_node_activate(p,{name = "mesecons_insulated:insulated_off", param2 = 1 } )
end
end
-- activate front wall
--TODO: refresh new value of wires
end
local function add_direction_to_pos(pos,direction)
return {x = pos.x + direction.x, y= pos.y, z = pos.z + direction.z }
end
local function can_move_node(pos,direction)
local node = minetest.get_node(pos)
local name = node.name
local param2= node.param2
if( name == "air" ) then
return true
end
if( name == "mesecons_insulated:insulated_off" ) or ( name == "mesecons_insulated:insulated_on" ) then
if (param2==0) or (param2==2) then
if( direction.z==0) then return true else return false end
elseif (param2==1) or (param2==3) then
if( direction.x == 0) then return true else return false end
end
else
return false
end
end
local function check_if_can_move(direction)
local pos1 = mesecons_automove.pos1
local pos2 = mesecons_automove.pos2
pos1,pos2 = sort_xz(pos1,pos2)
local wall = get_front_wall(pos1,pos2,direction)
pos1 = wall.pos1
pos2 = wall.pos2
local v
if( pos1.x == pos2.x ) then
if( pos1.z < pos2.z ) then
v = {z=1,x=0}
else
v = {z=-1,x=0}
end
else
-- pos1.z == pos2.z
if( pos1.x < pos2.x ) then
v = {z=0,x=1}
else
v ={ z=0,x=-1}
end
end
local current = pos1
while( eq_pos(current,pos2) == false ) do
if( can_move_node(current,direction) == false ) then
return false
end
current.x = current.x + v.x
current.z = current.z + v.z
end
-- do last node
if( can_move_node(current,direction) == false ) then
return false
end
return true
end
local function move_selection_left(rad)
local v = radians_to_vectors(rad)
local pos1 = mesecons_automove.pos1
local pos2 = mesecons_automove.pos2
if( pos1 == nil ) then return end
if( pos2 == nil ) then return end
if( check_if_can_move(v.left) == false ) then return end
move_nodes(v.left)
pos1.x = pos1.x + v.left.x
pos1.z = pos1.z + v.left.z
pos2.x = pos2.x + v.left.x
pos2.z = pos2.z + v.left.z
mesecons_automove.pos1 = pos1
mesecons_automove.pos2 = pos2
update_selection()
end
local function move_selection_right(rad)
local v = radians_to_vectors(rad)
local pos1 = mesecons_automove.pos1
local pos2 = mesecons_automove.pos2
if( pos1 == nil ) then return end
if( pos2 == nil ) then return end
if( check_if_can_move(v.right) == false ) then return end
move_nodes(v.right)
pos1.x = pos1.x + v.right.x
pos1.z = pos1.z + v.right.z
pos2.x = pos2.x + v.right.x
pos2.z = pos2.z + v.right.z
mesecons_automove.pos1 = pos1
mesecons_automove.pos2 = pos2
update_selection()
end
minetest.register_entity(":mesecons_automove:pos1", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1, },
textures = {"worldedit_pos1.png", "worldedit_pos1.png",
"worldedit_pos1.png", "worldedit_pos1.png",
"worldedit_pos1.png", "worldedit_pos1.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
static_save = false,
},
on_activate = function(self, staticdata, dtime_s)
end,
on_punch = function(self, hitter)
self.object:remove()
mesecons_automove.pos1e = nil
mesecons_automove.pos1 = nil
mesecons_automove.pos2 = nil
if( mesecons_automove.pos2e ~= nil ) then
mesecons_automove.pos2e:remove()
mesecons_automove.pos2e = nil
end
print("debug.self:remove()")
end,
on_blast = function(self, damage)
return false, false, {} -- don't damage or knockback
end,
})
minetest.register_entity(":mesecons_automove:pos2", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1},
textures = {"worldedit_pos2.png", "worldedit_pos2.png",
"worldedit_pos2.png", "worldedit_pos2.png",
"worldedit_pos2.png", "worldedit_pos2.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
static_save = false,
},
on_activate = function(self, staticdata, dtime_s)
end,
on_punch = function(self, hitter)
self.object:remove()
mesecons_automove.pos2e = nil
mesecons_automove.pos2 = nil
mesecons_automove.pos1 = nil
if( mesecons_automove.pos1e ~= nil) then
mesecons_automove.pos1e:remove()
end
end,
on_blast = function(self, damage)
return false, false, {} -- don't damage or knockback
end,
})
minetest.register_entity(":mesecons_automove:move_region", {
initial_properties = {
visual = "upright_sprite",
textures = {"worldedit_cube.png"},
visual_size = {x=10, y=1.1},
physical = false,
static_save = false,
},
on_activate = function(self, staticdata, dtime_s)
end,
on_punch = function(self, hitter)
self.object:remove()
end,
on_blast = function(self, damage)
return false, false, {} -- don't damage or knockback
end,
})
--minetest.register_craftitem("mesecons_autowire:move", {
minetest.register_tool("mesecons_autowire:select", {
description = "Tool Autoselect",
inventory_image = "tool_autoselect.png",
stack_max = 1,
groups = { tool =1 },
on_use = function(itemstack, user, pointed_thing)
if pointed_thing == nil then return end
if pointed_thing.type == "nothing" then
--unselect
mesecons_automove.pos1 = nil
mesecons_automove.pos2 = nil
update_selection()
return
elseif pointed_thing.type == "node" then
--select pos1
local node_pos = pointed_thing.under
if( mesecons_automove.pos1e ~= nil ) then
mesecons_automove.pos1e:remove()
end
if( is_circuit_element(node_pos) ) then
mesecons_automove.pos1 = node_pos
else
mesecons_automove.pos1 = pointed_thing.above
end
mesecons_automove.pos1e = minetest.add_entity(mesecons_automove.pos1,"mesecons_automove:pos1")
end
end,
on_place = function(itemstack, user, pointed_thing)
if pointed_thing == nil then return end
if pointed_thing.type == "node" then
local node_pos = pointed_thing.under
if( mesecons_automove.pos2e ~= nil ) then
mesecons_automove.pos2e:remove()
end
if( is_circuit_element(node_pos) ) then
mesecons_automove.pos2 = node_pos
else
mesecons_automove.pos2 = pointed_thing.above
end
mesecons_automove.pos2e = minetest.add_entity(mesecons_automove.pos2,"mesecons_automove:pos2")
end
end,
on_secondary_use = function(itemstack, user, pointed_thing)
if pointed_thing == nil then return end
if pointed_thing.type == "nothing" then
--move
end
end
})
minetest.register_tool("mesecons_autowire:move", {
description = "Tool Automove",
inventory_image = "tool_automove.png",
stack_max = 1,
groups = { tool =1 },
on_use = function(itemstack, user, pointed_thing)
if mesecons_automove.pos1 == nil then return end
if mesecons_automove.pos2 == nil then return end
move_selection_left(user:get_look_horizontal())
end,
on_place = function(itemstack, user, pointed_thing)
if mesecons_automove.pos1 == nil then return end
if mesecons_automove.pos2 == nil then return end
move_selection_right(user:get_look_horizontal())
end,
on_secondary_use = function(itemstack, user, pointed_thing)
if mesecons_automove.pos1 == nil then return end
if mesecons_automove.pos2 == nil then return end
move_selection_right(user:get_look_horizontal())
end
})