mirror of
https://gitlab.com/deetmit/mesecons_x.git
synced 2024-08-19 21:04:13 +02:00
628 lines
16 KiB
Lua
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
|
|
|
|
|
|
})
|
|
|