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 })