Add circuit.lua, autowire.lua

This commit is contained in:
Deet Mit 2020-07-18 13:41:25 +02:00
parent 4c6ae2be18
commit a332d55bd8
9 changed files with 554 additions and 9 deletions

@ -342,6 +342,23 @@ function delete(pos)
end
local function delete_all_selection(pos1,pos2)
local xf = math.min(pos1.x,pos2.x)
local xt = math.max(pos1.x,pos2.x)
local zf = math.min(pos1.z,pos2.z)
local zt = math.max(pos1.z,pos2.z)
for i=xf,xt do
for k = zf,zt do
local cur = { x=i,z=k,y=pos1.y}
minetest.set_node(cur,{name="air"})
end
end
end
minetest.register_craftitem("mesecons_autowire:delete", {
description = "Tool Autodelete",
inventory_image = "tool_autodelete.png",
@ -350,13 +367,25 @@ minetest.register_craftitem("mesecons_autowire:delete", {
on_place = function(itemstack, user, pointed_thing)
local pos = pointed_thing.under
if( is_wire(pos) ) then
delete(pos)
elseif( is_sticky(pos) ) then
delete(pos)
end
if pointed_thing.type == "node" then
if( is_wire(pos) ) then
delete(pos)
elseif( is_sticky(pos) ) then
delete(pos)
end
end
end,
on_secondary_use = function(itemstack, user, pointed_thing)
if pointed_thing.type == "nothing" then
if check_selection(mesecons_automove.pos1,mesecons_automove.pos2) then
delete_all_selection(mesecons_automove.pos1,mesecons_automove.pos2)
end
end
end
})

@ -30,7 +30,30 @@ local function sort_xz(p1,p2)
return p1,p2
end
local function update_selection()
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
@ -44,6 +67,8 @@ local function update_selection()
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
@ -518,7 +543,10 @@ minetest.register_tool("mesecons_autowire:select", {
on_use = function(itemstack, user, pointed_thing)
if pointed_thing == nil then return end
if pointed_thing.type == "nothing" then
--move
--unselect
mesecons_automove.pos1 = nil
mesecons_automove.pos2 = nil
update_selection()
return
elseif pointed_thing.type == "node" then

@ -235,6 +235,8 @@ minetest.register_craftitem("mesecons_autowire:wire", {
else
mesecons_autowire.pos1 = pointed_thing.above
end
print("debug.DB="..dump(mesecons_autowire))
end,
on_place = function(itemstack, user, pointed_thing)
if not pointed_thing then return end

@ -0,0 +1,485 @@
-- support for MT game translation.
local S = default.get_translator
--[[
current = pos left bottom
posh = pos right bottom
posv = pos left top
depends where you look at
]]--
local function standarise_corners(pos1,pos2,direction)
--assert(pos1.y == pos2.y) TODO: how to solve the problem of selectin not flat region
local x1,x2,z1,z2,y
y = pos1.y
x1 = pos1.x
x2 = pos2.x
z1 = pos1.z
z2 = pos2.z
x1,x2 = math.min(x1,x2), math.max(x1,x2)
z1,z2 = math.min(z1,z2), math.max(z1,z2)
local p1,p2,p3,p4
p1 = { x=x1,y=y,z=z1 }
p2 = { x=x2,y=y,z=z1 }
p3 = { x=x1,y=y,z=z2 }
p4 = { x=x2,y=y,z=z2 }
if( direction.x == -1 ) then
return p2,p4,p1
elseif( direction.x == 1 ) then
return p3,p1,p4
elseif( direction.z == -1 ) then
return p4,p3,p2
else
return p1,p2,p3
end
end
local function iter_vectors(direction)
local dx = direction.x
local dz = direction.z
if( direction.z == 1 ) then
return {x=1,z=0},{x=0,z=1}
elseif( direction.z == -1 ) then
return {x=-1,z=0},{x=0,z=-1}
elseif( direction.x == -1 ) then
return {x=0,z=1},{x=-1,z=0}
else
return {x=0,z=-1},{x=1,z=0}
end
end
function check_selection(pos1,pos2)
if( pos1 == nil ) then return false end
if( pos2 == nil ) then return false end
return true
end
local function add_direct_to_pos(pos,direc)
return { x = pos.x + direc.x , y = pos.y, z = pos.z + direc.z }
end
local function store_nodes(p1,p2,direction)
local pos1,pos2 = p1,p2
local tab = {}
if( check_selection(pos1,pos2) == false ) then
return nil
end
local corner, maxh, maxv = standarise_corners(pos1,pos2,direction)
local inch,incv = iter_vectors(direction)
local i,k = 1,1
local cur,curv,curh = corner,corner,corner
while true do
i = 1
tab[k] = {}
while true do
tab[k][i] = minetest.get_node(cur)
if( eq_pos(curh,maxh) ) then
break
end
curh = add_direct_to_pos(curh,inch)
cur = add_direct_to_pos(cur, inch)
i = i + 1
end
if( eq_pos(curv,maxv) ) then
break
end
curv = add_direct_to_pos(curv,incv)
cur = curv
curh = corner
k = k +1
end
--print("["..i.."]["..k.."]="..name)
--print("table = ".. dump(tab))
return tab
end
local function radians_to_direction_looking_forward(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 {x=0, z =1 }
elseif (rad >= 1/4*pi) and (rad <= (1/2+1/4)*pi) then
return {x=-1,z=0}
elseif (rad >= (1-1/4)*pi ) and (rad <= (3/2-1/4)*pi ) then
return {x=0,z=-1}
else
return {x=1,z=0}
end
end
local function store_nodes_from_selection(rad)
local direction = radians_to_direction_looking_forward(rad)
return store_nodes(mesecons_automove.pos1, mesecons_automove.pos2,direction)
end
local function circuit_on_place(itemstack, user, pointed_thing)
print("debug:on_plalce_circuit")
end
local max_text_size = 10000
local max_title_size = 80
local short_title_size = 35
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "mesecons_autowire:circuit" then return end
if( fields.save and fields.title ) then
local stack = player:get_wielded_item()
local inv = player:get_inventory()
local new_stack = nil
local meta = stack:get_meta()
local data = meta:to_table().fields
-- if no nodes then save nodes
if not data.nodes then
local rad = player:get_look_horizontal()
local tab = store_nodes_from_selection(rad)
print("tab="..dump(tab))
if( tab ) then
data.nodes = minetest.serialize(tab)
data.rad = rad
else
return
end
end
print("debug.af="..dump(data))
local count = stack:get_count()
if( count <= 0 ) then return end
if count == 1 then
inv:remove_item("main",stack)
else
stack:set_count(count - 1)
end
new_stack = ItemStack("mesecons_autowire:circuit_full")
if not fields.text then fields.text = "" end
if not fields.title then fields.title = "" end
data.title = fields.title:sub(1, max_title_size)
local short_title = data.title
-- Don't bother triming the title if the trailing dots would make it longer
if #short_title > short_title_size + 3 then
short_title = short_title:sub(1, short_title_size) .. "..."
end
data.description = S(short_title)
data.text = fields.text:sub(1, max_text_size)
data.text = data.text:gsub("\r\n", "\n"):gsub("\r", "\n")
if new_stack then
new_stack:get_meta():from_table({ fields = data})
if inv:room_for_item("main", new_stack) then
inv:add_item("main", new_stack)
else
minetest.add_item(player:get_pos(), new_stack)
end
end
--debug
end
end)
local function show_dialog(itemstack,user,pointed_thing)
local player_name = user:get_player_name()
local formspec
local esc = minetest.formspec_escape
local meta = itemstack:get_meta()
local data = meta:to_table().fields
local title, text = data.title or "", data.text or ""
local nodes_string = "empty"
local nodes = minetest.deserialize(data.nodes)
if( nodes ) then
-- show nodes
nodes_string = "size = (".. #nodes[1] .. ","..#nodes .. ")"
end
formspec = "size[18,8]" ..
"field[0.5,0.5;7.5,1;title;"..S("Name")..";"..S(title).."]"..
"textarea[0.5,1.5;7.5,7;text;" .. esc(S("Description:")) .. ";" ..
esc(S(text)) .. "]" ..
"button_exit[2.5,7.5;3,1;save;" .. esc(S("Save")) .. "]" ..
"label[10,0.5;"..nodes_string.."]"..
""
minetest.show_formspec(player_name, "mesecons_autowire:circuit", formspec)
return itemstack
end
local function make_selection(nodes,pos,rad)
if nodes == nil then return end
--if check_selection(mesecons_automove.pos1,mesecons_automove.pos2) == false then return end
local vsize = #nodes
local hsize = #nodes[1]
print("dump"..dump(nodes) .. "====" .. dump(pos) .. "===" .. vsize .. "=" .. hsize )
local direction = radians_to_direction_looking_forward(rad)
mesecons_automove.pos1 = pos
local dx,dz = 0,0
print("dumpsirection="..dump(direction))
hsize = hsize -1
vsize = vsize -1
if direction.z == 1 then
dx,dz = hsize,vsize
elseif direction.z == -1 then
dx,dz = -hsize,-vsize
elseif direction.x == 1 then
dx,dz = vsize,-hsize
else
--dirextion.x == -1
dx,dz = -vsize,hsize
end
mesecons_automove.pos2 = { x=pos.x + dx, y=pos.y, z = pos.z+dz }
mesecons_automove.rad = rad
--print("debug.all="..dump(mesecons_automove))
update_selection()
end
local function direction_to_number(direction)
if( direction.z == 1 ) then
return 1
elseif( direction.x == 1 ) then
return 2
elseif(direction.z == -1 )then
return 3
else
return 4
end
end
local rotate_exceptions = {
"mesecons_extrawires:crossover_off",
"mesecons_extrawires:crossover_on",
"mesecons_morewires:xjunction_on",
"mesecons_morewires:xjunction_off"
}
local function is_exception(node)
for _,v in ipairs(rotate_exceptions) do
if( v == node.name ) then
return true
end
end
return false
end
local function special_case(node,rotate)
local new_node = node
local applied = false
if( node.name == "mesecons_extrawires:crossover_10") and (rotate % 2 == 1 ) then
new_node.name = "mesecons_extrawires:crossover_01"
new_node.param2 = 0
return new_node
elseif (node.name == "mesecons_extrawires:crossover_10") and (rotate % 2 == 0 ) then
new_node.name = "mesecons_extrawires:crossover_10"
new_node.param2 = 0
return new_node
elseif( node.name == "mesecons_extrawires:crossover_01" and (rotate % 2 == 1) ) then
new_node.name = "mesecons_extrawires:crossover_10"
new_node.param2 = 0
return new_node
elseif ( node.name == "mesecons_extrawires:crossover_01" and (rotate % 2 == 0 ) ) then
new_node.name = "mesecons_extrawires:crossover_01"
new_node.param2 = 0
return new_node
end
return nil
end
local function rotate_node(node, saved_direction,direction)
if( is_exception(node) ) then return node end
local values =
{
{0,1,2,3},
{3,0,1,2},
{2,3,0,1},
{1,2,3,0}
}
local rotate =
values[direction_to_number(saved_direction)][direction_to_number(direction)]
local new_node = special_case(node,rotate)
if( new_node ~= nil ) then return new_node end
new_node = node
new_node.param2 = (node.param2+rotate)%4
return new_node
end
local function paste_nodes(nodes,saved_direction,direction)
local pos1,pos2 = mesecons_automove.pos1,mesecons_automove.pos2
if( check_selection(pos1,pos2) == false ) then
return nil
end
local corner, maxh, maxv = standarise_corners(pos1,pos2,direction)
local inch,incv = iter_vectors(direction)
local tab = nodes
if tab == nil then return end
local maxi = #nodes[1]
local maxk = #nodes
local i,k = 1,1
local cur,curv,curh = corner,corner,corner
while true do
i = 1
while true do
--tab[k][i] = minetest.get_node(cur)
if( i<=maxi) and (k<=maxk) then
local n = rotate_node(tab[k][i],saved_direction,direction)
minetest.set_node(cur,n)
end
if( eq_pos(curh,maxh) ) then
break
end
curh = add_direct_to_pos(curh,inch)
cur = add_direct_to_pos(cur, inch)
i = i + 1
end
if( eq_pos(curv,maxv) ) then
break
end
curv = add_direct_to_pos(curv,incv)
cur = curv
curh = corner
k = k +1
end
end
local function on_use_circuit(itemstack, user, pointed_thing)
if( pointed_thing.type == "node" ) then
-- select region
local nodes = minetest.deserialize(itemstack:get_meta():to_table().fields.nodes)
local sel_pos
if( is_circuit_element(pointed_thing.under) ) then
sel_pos = pointed_thing.under
else
sel_pos = pointed_thing.above
end
make_selection(nodes,sel_pos,user:get_look_horizontal())
else
-- show dialog
show_dialog(itemstack,user,pointed_thing);
end
end
local function on_place_circuit(itemstack, user, pointed_thing)
if pointed_thing.type == "node" then
-- paste
end
local data = itemstack:get_meta():to_table()
local nodes = minetest.deserialize(data.fields.nodes)
local rad = tonumber( data.fields.rad )
paste_nodes(nodes,radians_to_direction_looking_forward(rad), radians_to_direction_looking_forward(mesecons_automove.rad))
end
minetest.register_craftitem("mesecons_autowire:circuit_empty", {
description = S("Circuit empty"),
inventory_image = "circuit_empty.png",
on_use = on_use_circuit
})
minetest.register_craftitem("mesecons_autowire:circuit_full", {
description = S("Circuit saved"),
inventory_image = "circuit_full.png",
groups = {not_in_creative_inventory = 1},
stack_max = 1,
on_use = on_use_circuit,
on_place = on_place_circuit,
on_secondary_use = on_place_circuit
})

@ -2,4 +2,5 @@ mesecons_autowire = {}
dofile(minetest.get_modpath("mesecons_autowire").."/utils.lua");
dofile(minetest.get_modpath("mesecons_autowire").."/auto_delete.lua");
dofile(minetest.get_modpath("mesecons_autowire").."/auto_wire.lua");
dofile(minetest.get_modpath("mesecons_autowire").."/auto_move.lua");
dofile(minetest.get_modpath("mesecons_autowire").."/auto_move.lua");
dofile(minetest.get_modpath("mesecons_autowire").."/circuit.lua");

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB