First commit, workinging sample
45
.luacheckrc
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
read_globals = {
|
||||||
|
"DIR_DELIM", "INIT",
|
||||||
|
|
||||||
|
"minetest", "core",
|
||||||
|
"dump", "dump2",
|
||||||
|
|
||||||
|
"Raycast",
|
||||||
|
"Settings",
|
||||||
|
"PseudoRandom",
|
||||||
|
"PerlinNoise",
|
||||||
|
"VoxelManip",
|
||||||
|
"SecureRandom",
|
||||||
|
"VoxelArea",
|
||||||
|
"PerlinNoiseMap",
|
||||||
|
"PcgRandom",
|
||||||
|
"ItemStack",
|
||||||
|
"AreaStore",
|
||||||
|
|
||||||
|
"vector",
|
||||||
|
|
||||||
|
table = {
|
||||||
|
fields = {
|
||||||
|
"copy",
|
||||||
|
"indexof",
|
||||||
|
"insert_all",
|
||||||
|
"key_value_swap",
|
||||||
|
"shuffle",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
string = {
|
||||||
|
fields = {
|
||||||
|
"split",
|
||||||
|
"trim",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
math = {
|
||||||
|
fields = {
|
||||||
|
"hypot",
|
||||||
|
"sign",
|
||||||
|
"factorial"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
388
blocks/cable.lua
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
--[[
|
||||||
|
cable_NS1 -> One connection from north to south
|
||||||
|
cable_NW1_ES1 -> One connection from north to west, and another from east to south
|
||||||
|
cable_NWE8_S8 -> One connection between north, west and east, 8bit single cable from south
|
||||||
|
cable_0 -> The one cable without connection
|
||||||
|
--]]
|
||||||
|
|
||||||
|
local nodebox_single = {
|
||||||
|
{-0.0625, -0.5, 0.25, 0.0625, -0.375, 0.5},
|
||||||
|
{-0.125, -0.5, 0.25, 0.125, -0.25, 0.5}
|
||||||
|
}
|
||||||
|
local nodebox_straight = {
|
||||||
|
{-0.0625, -0.5, -0.5, 0.0625, -0.375, 0.5},
|
||||||
|
{-0.125, -0.5, -0.5, 0.125, -0.25, 0.5}
|
||||||
|
}
|
||||||
|
local nodeboxes_corner = {
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.0625, 0.0625, -0.375, 0.0625}, -- NodeBox1
|
||||||
|
{-0.0625, -0.5, 0.0625, 0.0625, -0.375, 0.5}, -- NodeBox2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.125, 0.125, -0.25, 0.125}, -- NodeBox1
|
||||||
|
{-0.125, -0.5, 0.125, 0.125, -0.25, 0.5}, -- NodeBox2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local nodeboxes_jump = {
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.0625, -0.1875, -0.375, 0.0625}, -- NodeBox2
|
||||||
|
{0.1875, -0.5, -0.0625, 0.5, -0.375, 0.0625}, -- NodeBox3
|
||||||
|
{-0.3125, -0.1875, -0.0625, 0.3125, -0.0625, 0.0625}, -- NodeBox4
|
||||||
|
{-0.3125, -0.375, -0.0625, -0.1875, -0.1875, 0.0625}, -- NodeBox5
|
||||||
|
{0.1875, -0.375, -0.0625, 0.3125, -0.1875, 0.0625}, -- NodeBox6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.125, -0.1875, -0.25, 0.125}, -- NodeBox2
|
||||||
|
{0.1875, -0.5, -0.125, 0.5, -0.25, 0.125}, -- NodeBox3
|
||||||
|
{-0.4375, -0.1875, -0.125, 0.4375, 0.0625, 0.125}, -- NodeBox4
|
||||||
|
{-0.4375, -0.25, -0.125, -0.1875, -0.1875, 0.125}, -- NodeBox5
|
||||||
|
{0.1875, -0.25, -0.125, 0.4375, -0.1875, 0.125}, -- NodeBox6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local nodeboxes_ccorner = {
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.0625, -0.1875, -0.375, 0.0625}, -- NodeBox1
|
||||||
|
{-0.0625, -0.5, 0.1875, 0.0625, -0.375, 0.5}, -- NodeBox2
|
||||||
|
{-0.3125, -0.5, 0.0625, -0.1875, -0.375, 0.3125}, -- NodeBox3
|
||||||
|
{-0.1875, -0.5, 0.1875, -0.0625, -0.375, 0.3125}, -- NodeBox4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.125, -0.125, -0.25, 0.125}, -- NodeBox1
|
||||||
|
{-0.125, -0.5, 0.125, 0.125, -0.25, 0.5}, -- NodeBox2
|
||||||
|
{-0.375, -0.5, 0.125, -0.125, -0.25, 0.375}, -- NodeBox4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local nodeboxes_tri = {
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.0625, 0.5, -0.375, 0.0625}, -- NodeBox1
|
||||||
|
{-0.0625, -0.5, 0.0625, 0.0625, -0.375, 0.5}, -- NodeBox2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.125, 0.5, -0.25, 0.125}, -- NodeBox1
|
||||||
|
{-0.125, -0.5, 0.125, 0.125, -0.25, 0.5}, -- NodeBox2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local nodeboxes_cross = {
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.0625, 0.5, -0.375, 0.0625}, -- NodeBox1
|
||||||
|
{-0.0625, -0.5, 0.0625, 0.0625, -0.375, 0.5}, -- NodeBox2
|
||||||
|
{-0.0625, -0.5, -0.5, 0.0625, -0.375, -0.0625}, -- NodeBox3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{-0.5, -0.5, -0.125, 0.5, -0.25, 0.125}, -- NodeBox1
|
||||||
|
{-0.125, -0.5, 0.125, 0.125, -0.25, 0.5}, -- NodeBox2
|
||||||
|
{-0.125, -0.5, -0.5, 0.125, -0.25, -0.125}, -- NodeBox3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local nodebox_disconnected = {-0.125, -0.5, -0.125, 0.125, -0.25, 0.125}
|
||||||
|
|
||||||
|
local function rotateNodebox(nb,rot)
|
||||||
|
return
|
||||||
|
(math.fmod(rot,4)==0) and {nb[1],nb[2],nb[3],nb[4],nb[5],nb[6]} or
|
||||||
|
(math.fmod(rot,4)==1) and {nb[3],nb[2],-nb[1],nb[6],nb[5],-nb[4]} or
|
||||||
|
(math.fmod(rot,4)==2) and {-nb[1],nb[2],-nb[3],-nb[4],nb[5],-nb[6]} or
|
||||||
|
(math.fmod(rot,4)==3) and {-nb[3],nb[2],nb[1],-nb[6],nb[5],nb[4]} or
|
||||||
|
nb -- Should not happen
|
||||||
|
end
|
||||||
|
local function rotate4dir(conn,r)
|
||||||
|
local function rotate4dirOnce(conn)
|
||||||
|
return math.floor(conn/2) + 8*math.fmod(conn,2)
|
||||||
|
end
|
||||||
|
local x = math.fmod(conn,16)
|
||||||
|
for i=1,r do
|
||||||
|
x = rotate4dirOnce(x)
|
||||||
|
end
|
||||||
|
return (conn - math.fmod(conn,16) + x)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function constArray(val,size)
|
||||||
|
local t = {}
|
||||||
|
for i=1,size
|
||||||
|
do
|
||||||
|
table.insert(t,val)
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
name: the name of the cable
|
||||||
|
nodeboxes: All the rendered nodeboxes
|
||||||
|
connections: A list of connections between NSEW (N=8,E=4,S=2,W=1), +16 when it is 8bit
|
||||||
|
ex: {4+2,16+1} -> ES + W8
|
||||||
|
nbconn: Which correspond each nodebox correspond to
|
||||||
|
ex: {1,1,2,1} -> nodeboxes 1,2,3 correspond to connection ES, and nodebox 2 correspond to connection W
|
||||||
|
--]]
|
||||||
|
circuits.cablesnb = {}
|
||||||
|
circuits.cablesconn = {}
|
||||||
|
circuits.cablesnbconn = {}
|
||||||
|
local function createCables(name,nodeboxes,connections,nbconn)
|
||||||
|
minetest.register_node("circuits:cable_"..name, {
|
||||||
|
tiles = {
|
||||||
|
"cable_gray.png",
|
||||||
|
"cable_gray.png",
|
||||||
|
"cable_gray.png",
|
||||||
|
"cable_gray.png",
|
||||||
|
"cable_gray.png",
|
||||||
|
"cable_gray.png",
|
||||||
|
},
|
||||||
|
drawtype = "nodebox",
|
||||||
|
paramtype = "light",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = nodeboxes
|
||||||
|
},
|
||||||
|
groups = {circuitry = 1,dig_immediate = 3}
|
||||||
|
})
|
||||||
|
|
||||||
|
if name == "EW8_N1_S1"
|
||||||
|
then print(dump(connections)) end
|
||||||
|
|
||||||
|
-- We sort the connections and nbconn
|
||||||
|
local connections2 = table.copy(connections)
|
||||||
|
table.sort(connections2)
|
||||||
|
local perm = table.arrperm(connections,connections2)
|
||||||
|
local nbconn2 = {}
|
||||||
|
for i,v in ipairs(nbconn)
|
||||||
|
do
|
||||||
|
nbconn2[i] = perm[v]
|
||||||
|
end
|
||||||
|
if name == "EW8_N1_S1"
|
||||||
|
then print(dump(connections2)) end
|
||||||
|
|
||||||
|
circuits.cablesnb[name] = nodeboxes
|
||||||
|
circuits.cablesconn[name] = connections2
|
||||||
|
circuits.cablesnbconn[name] = nbconn2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- cable_NSEW0
|
||||||
|
for v=1,2 do
|
||||||
|
createCables("NSEW"..tostring((v-1)*7+1),nodeboxes_cross[v],{(v-1)*16+8+4+2+1},constArray(1,#nodeboxes_cross[v]))
|
||||||
|
end
|
||||||
|
|
||||||
|
--[
|
||||||
|
-- cable_NW0_SE0
|
||||||
|
-- cable_NE0_SW0
|
||||||
|
-- cable_NS0_EW0
|
||||||
|
for v0=1,2 do
|
||||||
|
for v1=1,2 do
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
for _,nb in ipairs(nodeboxes_ccorner[v0]) do
|
||||||
|
table.insert(nodeboxes, nb)
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
end
|
||||||
|
for _,nb in ipairs(nodeboxes_ccorner[v1]) do
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nb,2))
|
||||||
|
table.insert(nbconn, 2)
|
||||||
|
end
|
||||||
|
createCables("NW"..tostring((v0-1)*7+1).."_SE"..tostring((v1-1)*7+1),nodeboxes,{(v0-1)*16+8+1,(v1-1)*16+4+2},nbconn)
|
||||||
|
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
for _,nb in ipairs(nodeboxes_ccorner[v0]) do
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nb,1))
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
end
|
||||||
|
for _,nb in ipairs(nodeboxes_ccorner[v1]) do
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nb,3))
|
||||||
|
table.insert(nbconn, 2)
|
||||||
|
end
|
||||||
|
createCables("NE"..tostring((v0-1)*7+1).."_SW"..tostring((v1-1)*7+1),nodeboxes,{(v0-1)*16+8+4,(v1-1)*16+2+1},nbconn)
|
||||||
|
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
table.insert(nodeboxes, nodebox_straight[v0])
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
for _,nb in ipairs(nodeboxes_jump[v1]) do
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nb,2))
|
||||||
|
table.insert(nbconn, 2)
|
||||||
|
end
|
||||||
|
createCables("NS"..tostring((v0-1)*7+1).."_EW"..tostring((v1-1)*7+1),nodeboxes,{(v0-1)*16+8+2,(v1-1)*16+4+1},nbconn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- cable_AB0_C0_D0 -- ("NW","NE","SE","SW") * (/ + C0 + D0 + C0D0)
|
||||||
|
-- cable_AB0_C0_D0 -- ("NS" "EW") * (/ + C0 + D0 + C0D0)
|
||||||
|
for v=1,2 do
|
||||||
|
for v1=0,2 do
|
||||||
|
for v2=0,2 do
|
||||||
|
for r,rn in ipairs({{"NW","E","S"},{"NE","S","W"},{"SE","W","N"},{"SW","N","E"}}) do
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
local connz = {rotate4dir((v-1)*16+8+1,r-1)}
|
||||||
|
for _,nb in ipairs(nodeboxes_corner[v]) do
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nb,r-1))
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
end
|
||||||
|
if v1 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v1],r))
|
||||||
|
table.insert(nbconn, 2)
|
||||||
|
table.insert(connz,rotate4dir((v1-1)*16+4,r-1))
|
||||||
|
end
|
||||||
|
if v2 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v2],r+1))
|
||||||
|
table.insert(nbconn, v1==0 and 2 or 3)
|
||||||
|
table.insert(connz,rotate4dir((v2-1)*16+2,r-1))
|
||||||
|
end
|
||||||
|
createCables(
|
||||||
|
rn[1]..tostring((v-1)*7+1)..
|
||||||
|
(v1~=0 and ("_"..rn[2]..tostring((v1-1)*7+1)) or "")..
|
||||||
|
(v2~=0 and ("_"..rn[3]..tostring((v2-1)*7+1)) or "")
|
||||||
|
,nodeboxes,connz,nbconn
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
for r,rn in ipairs({{"NS","E","W"},{"EW","N","S"}}) do
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
local connz = {rotate4dir((v-1)*16+8+2,r-1)}
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_straight[v],r-1))
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
if v1 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v1],r))
|
||||||
|
table.insert(nbconn, 2)
|
||||||
|
table.insert(connz,rotate4dir((v1-1)*16+4,r-1))
|
||||||
|
end
|
||||||
|
if v2 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v2],r+2))
|
||||||
|
table.insert(nbconn, v1==0 and 2 or 3)
|
||||||
|
table.insert(connz,rotate4dir((v2-1)*16+1,r-1))
|
||||||
|
end
|
||||||
|
createCables(
|
||||||
|
rn[1]..tostring((v-1)*7+1)..
|
||||||
|
(v1~=0 and ("_"..rn[2]..tostring((v1-1)*7+1)) or "")..
|
||||||
|
(v2~=0 and ("_"..rn[3]..tostring((v2-1)*7+1)) or ""),
|
||||||
|
nodeboxes,connz,nbconn
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- "cable_A0_B0_C0_D0" -- (n s e w ns ...)
|
||||||
|
for v1=0,2 do
|
||||||
|
for v2=0,2 do
|
||||||
|
for v3=0,2 do
|
||||||
|
for v4=0,2 do
|
||||||
|
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
local name = ""
|
||||||
|
local connz = {}
|
||||||
|
if v1 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v1],0))
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
table.insert(connz,(v1-1)*16+8)
|
||||||
|
name = name.."_N"..tostring((v1-1)*7+1)
|
||||||
|
end
|
||||||
|
if v2 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v2],1))
|
||||||
|
table.insert(nbconn, #nbconn+1)
|
||||||
|
table.insert(connz,(v2-1)*16+4)
|
||||||
|
name = name.."_E"..tostring((v2-1)*7+1)
|
||||||
|
end
|
||||||
|
if v3 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v3],2))
|
||||||
|
table.insert(nbconn, #nbconn+1)
|
||||||
|
table.insert(connz,(v3-1)*16+2)
|
||||||
|
name = name.."_S"..tostring((v3-1)*7+1)
|
||||||
|
end
|
||||||
|
if v4 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v4],3))
|
||||||
|
table.insert(nbconn, #nbconn+1)
|
||||||
|
table.insert(connz,(v4-1)*16+1)
|
||||||
|
name = name.."_W"..tostring((v4-1)*7+1)
|
||||||
|
end
|
||||||
|
if name == "" then
|
||||||
|
table.insert(nodeboxes, nodebox_disconnected)
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
table.insert(connz,(v1-1)*16+0) -- special case of no connection
|
||||||
|
name = "_zero"
|
||||||
|
end
|
||||||
|
|
||||||
|
createCables(string.sub(name,2,-1),nodeboxes,connz,nbconn)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- "cable_ABC0_D0" -- ("NEW","NES","ESW","SWN") * (/ + D0)
|
||||||
|
for v=1,2 do
|
||||||
|
for v1=0,2 do
|
||||||
|
for r,rn in ipairs({{"NEW","S"},{"NES","W"},{"ESW","N"},{"SWN","E"}}) do
|
||||||
|
local nodeboxes = {}
|
||||||
|
local nbconn = {}
|
||||||
|
local connz = {rotate4dir((v-1)*16+8+4+1,r-1)}
|
||||||
|
for _,nb in ipairs(nodeboxes_tri[v]) do
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nb,r-1))
|
||||||
|
table.insert(nbconn, 1)
|
||||||
|
end
|
||||||
|
if v1 ~= 0 then
|
||||||
|
table.insert(nodeboxes, rotateNodebox(nodebox_single[v1],r+1))
|
||||||
|
table.insert(nbconn, 2)
|
||||||
|
table.insert(connz,rotate4dir((v1-1)*16+2,r-1))
|
||||||
|
end
|
||||||
|
createCables(
|
||||||
|
rn[1]..tostring((v-1)*7+1)..
|
||||||
|
(v1~=0 and ("_"..rn[2]..tostring((v1-1)*7+1)) or ""),
|
||||||
|
nodeboxes,connz,nbconn
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
|
circuits.cablesfromconn = table.invert(circuits.cablesconn)
|
||||||
|
|
||||||
|
|
||||||
|
function circuits.rotateCable(name,r)
|
||||||
|
local conn = circuits.cablesconn[name]
|
||||||
|
local newconn = {}
|
||||||
|
for i,v in ipairs(conn)
|
||||||
|
do
|
||||||
|
newconn[i] = rotate4dir(v,r)
|
||||||
|
end
|
||||||
|
table.sort(newconn)
|
||||||
|
return table.getkey1(circuits.cablesconn,newconn)
|
||||||
|
end
|
||||||
|
|
||||||
|
function circuits.connectInCable(name,a,b)
|
||||||
|
local conns = table.copy(circuits.cablesconn[name])
|
||||||
|
local cia = circuits.cablesnbconn[name][a]
|
||||||
|
local cib = circuits.cablesnbconn[name][b]
|
||||||
|
local conna = conns[cia]
|
||||||
|
local connb = conns[cib]
|
||||||
|
|
||||||
|
-- If mismatch, v is that of firstly selected cable
|
||||||
|
local v = math.fmod(math.floor(conna/16),2)
|
||||||
|
conns[cia] = math.fmod(conna,16) + math.fmod(connb,16) + v*16
|
||||||
|
table.remove(conns,cib)
|
||||||
|
|
||||||
|
table.sort(conns)
|
||||||
|
return table.getkey1(circuits.cablesconn,conns)
|
||||||
|
end
|
||||||
|
|
||||||
|
function circuits.disconnectInCable(name,a)
|
||||||
|
local conns = table.copy(circuits.cablesconn[name])
|
||||||
|
local cindex = circuits.cablesnbconn[name][a]
|
||||||
|
local conn = conns[cindex]
|
||||||
|
|
||||||
|
table.remove(conns,cindex)
|
||||||
|
|
||||||
|
if not (conn == 1 or conn == 2 or conn == 4 or conn == 8 or conn == 17 or conn == 18 or conn == 20 or conn == 24)
|
||||||
|
then -- The connection was more than one-sided, so we recreate the «tips»
|
||||||
|
if math.fmod(math.floor(conn/1),2)==1
|
||||||
|
then table.insert(conns,conn>=16 and 17 or 1) end
|
||||||
|
if math.fmod(math.floor(conn/2),2)==1
|
||||||
|
then table.insert(conns,conn>=16 and 18 or 2) end
|
||||||
|
if math.fmod(math.floor(conn/4),2)==1
|
||||||
|
then table.insert(conns,conn>=16 and 20 or 4) end
|
||||||
|
if math.fmod(math.floor(conn/8),2)==1
|
||||||
|
then table.insert(conns,conn>=16 and 24 or 8) end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(conns)
|
||||||
|
return table.getkey1(circuits.cablesconn,conns)
|
||||||
|
end
|
||||||
39
blocks/circuit.lua
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
local _contexts = {}
|
||||||
|
|
||||||
|
function circuits.setNameFormspec(targetType, defaultName)
|
||||||
|
|
||||||
|
local text = "Please enter the name of this " .. targetType
|
||||||
|
|
||||||
|
local formspec = {
|
||||||
|
"formspec_version[4]",
|
||||||
|
"size[6,3.476]",
|
||||||
|
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
|
||||||
|
"field[0.375,1.25;5.25,0.8;name;".. minetest.formspec_escape(targetType) .. " name;"..(defaultName or "").."]",
|
||||||
|
"button[1.5,2.3;3,0.8;commit;OK]"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- table.concat is faster than string concatenation - `..`
|
||||||
|
return table.concat(formspec, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
function circuits.showSetNameFormspec(playerName, targetName)
|
||||||
|
minetest.show_formspec(playerName, "circuits:setNameFormSpec", circuits.setNameFormspec(targetName))
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
|
if formname ~= "circuits:setNameFormSpec" then return end
|
||||||
|
|
||||||
|
if fields.commit then
|
||||||
|
local pname = player:get_player_name()
|
||||||
|
minetest.chat_send_all(pname .. " guessed " .. fields.name)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_node("circuits:circuitBlock", {
|
||||||
|
description = "Circuit Block",
|
||||||
|
tiles = {"circuit_block.png"},
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
circuits.discoverBlocks(pos)
|
||||||
|
end,
|
||||||
|
groups = {circuitry = 1,dig_immediate = 3}
|
||||||
|
})
|
||||||
126
blocks/component.lua
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
|
||||||
|
--[[
|
||||||
|
0 : x+,z+
|
||||||
|
1 : TODO finish the comment
|
||||||
|
--]]
|
||||||
|
local function vecTo8dir(vec)
|
||||||
|
local x = vec[1]
|
||||||
|
local z = vec[3]
|
||||||
|
return
|
||||||
|
x>=0 and z>=0 and z<=x and 0 or
|
||||||
|
x>=0 and z>=0 and z>x and 1 or
|
||||||
|
x<0 and z>=0 and -z<=x and 2 or
|
||||||
|
x<0 and z>=0 and -z>x and 3 or
|
||||||
|
x<0 and z<0 and z>=x and 4 or
|
||||||
|
x<0 and z<0 and z<x and 5 or
|
||||||
|
x>=0 and z<0 and -z>=x and 6 or
|
||||||
|
x>=0 and z<0 and -z<x and 7 or
|
||||||
|
0 -- Should not happen
|
||||||
|
end
|
||||||
|
local function addToPos8dir(dir,pos,w,h)
|
||||||
|
local x = pos[1]
|
||||||
|
local y = pos[2]
|
||||||
|
local z = pos[3]
|
||||||
|
return
|
||||||
|
dir == 0 and {x = x+h, y = y, z = z+w} or
|
||||||
|
dir == 1 and {x = x+w, y = y, z = z+h} or
|
||||||
|
dir == 2 and {x = x-w, y = y, z = z+h} or
|
||||||
|
dir == 3 and {x = x-h, y = y, z = z+w} or
|
||||||
|
dir == 4 and {x = x-h, y = y, z = z-w} or
|
||||||
|
dir == 5 and {x = x-w, y = y, z = z-h} or
|
||||||
|
dir == 6 and {x = x+w, y = y, z = z-h} or
|
||||||
|
dir == 7 and {x = x+h, y = y, z = z-w} or
|
||||||
|
pos -- Should not happen
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Removes a node without calling on on_destruct()
|
||||||
|
-- We use this to mess with bed nodes without causing unwanted recursion.
|
||||||
|
local function remove_no_destruct(pos)
|
||||||
|
minetest.swap_node(pos, {name = "air"})
|
||||||
|
minetest.remove_node(pos) -- Now clear the meta
|
||||||
|
minetest.check_for_falling(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node("circuits:component_head", {
|
||||||
|
drawtype = "block",
|
||||||
|
tiles = {"component.png"},
|
||||||
|
groups = {circuitry = 1,dig_immediate = 3},
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local w = 3
|
||||||
|
local h = 5
|
||||||
|
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local node = minetest.get_node(under)
|
||||||
|
local udef = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
|
-- Rightclick is prioritary
|
||||||
|
if udef and udef.on_rightclick and
|
||||||
|
not (placer and placer:is_player() and
|
||||||
|
placer:get_player_control().sneak) then
|
||||||
|
return udef.on_rightclick(under, node, placer, itemstack,
|
||||||
|
pointed_thing) or itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pos will be the head location
|
||||||
|
local pos
|
||||||
|
if udef and udef.buildable_to then
|
||||||
|
pos = under
|
||||||
|
else
|
||||||
|
pos = pointed_thing.above
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local player_name = placer and placer:get_player_name() or ""
|
||||||
|
|
||||||
|
local dir = placer and placer:get_look_dir() and
|
||||||
|
vecTo8dir(placer:get_look_dir()) or 0
|
||||||
|
|
||||||
|
for i = 0,w*h-1 do
|
||||||
|
local loc = addToPos8dir(dir,pos,i%w,(i-i%w)/w)
|
||||||
|
local node_def = minetest.registered_nodes[minetest.get_node(loc).name]
|
||||||
|
if not node_def or not node_def.buildable_to then
|
||||||
|
-- Then we cannot build here
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- If we reached this point, we can build the component
|
||||||
|
minetest.set_node(pos, {name = "circuits:component_head", param2 = dir})
|
||||||
|
for i = 1,w*h-1 do
|
||||||
|
local loc = addToPos8dir(dir,pos,i%w,(i-i%w)/w)
|
||||||
|
minetest.set_node(loc, {name = "circuits:component_tail", param2 = dir})
|
||||||
|
end
|
||||||
|
|
||||||
|
if not minetest.is_creative_enabled(player_name) then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
on_destruct = function(pos)
|
||||||
|
local w = 3
|
||||||
|
local h = 5
|
||||||
|
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
|
||||||
|
dir = node.param2
|
||||||
|
|
||||||
|
remove_no_destruct(pos) -- Should be circuits:component_head
|
||||||
|
for i = 1,w*h-1 do
|
||||||
|
local loc = addToPos8dir(dir,pos,i%w,(i-i%w)/w)
|
||||||
|
local onode = minetest.get_node(loc)
|
||||||
|
if onode.name == "circuits:component_tail" and onode.param2 == dir
|
||||||
|
then
|
||||||
|
remove_no_destruct(loc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("circuits:component_tail", {
|
||||||
|
drawtype = "block",
|
||||||
|
paramtype2 = "4dir",
|
||||||
|
groups = {circuitry = 1},
|
||||||
|
-- Which direction is the one of the head block
|
||||||
|
tiles = {"component.png^[colorizehsl:120"}
|
||||||
|
})
|
||||||
57
circuits.lua
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
-- component {
|
||||||
|
-- inputs: ["in1": bit, "in2": bit, "inB": byte],
|
||||||
|
-- outputs: ["out": byte],
|
||||||
|
-- name: alu0,
|
||||||
|
-- optiCompute: fun
|
||||||
|
-- contents: {
|
||||||
|
--
|
||||||
|
-- }
|
||||||
|
-- }
|
||||||
|
|
||||||
|
function circuits.computeCircuit(circuit, input)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function has_value (tab, len, val)
|
||||||
|
for i = 1, len do
|
||||||
|
if tab[i].x == val.x and tab[i].y == val.y and tab[i].z == val.z then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function circuits.discoverBlocks(pos)
|
||||||
|
local i = 2
|
||||||
|
local j = 1
|
||||||
|
local poz = {}
|
||||||
|
poz[1] = pos
|
||||||
|
while (j<i)
|
||||||
|
do
|
||||||
|
local p = poz[j]
|
||||||
|
j = j+1
|
||||||
|
print(dump(poz))
|
||||||
|
print(i)
|
||||||
|
print(j)
|
||||||
|
local neighbourhood = {
|
||||||
|
{x = p.x+1, y = p.y, z = p.z},
|
||||||
|
{x = p.x-1, y = p.y, z = p.z},
|
||||||
|
{x = p.x, y = p.y+1, z = p.z},
|
||||||
|
{x = p.x, y = p.y-1, z = p.z},
|
||||||
|
{x = p.x, y = p.y, z = p.z+1},
|
||||||
|
{x = p.x, y = p.y, z = p.z-1}
|
||||||
|
}
|
||||||
|
for p2=1,6
|
||||||
|
do
|
||||||
|
local n = neighbourhood[p2]
|
||||||
|
if((not has_value(poz,i-1,n)) and (minetest.get_item_group(minetest.get_node(n).name,"circuitry")==1))
|
||||||
|
then
|
||||||
|
poz[i] = n
|
||||||
|
i = i+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.chat_send_all("Discovered ".. (i-1) .. " blocks")
|
||||||
|
end
|
||||||
53
init.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
circuits = {}
|
||||||
|
|
||||||
|
dofile(minetest.get_modpath("circuits") .. "/utils.lua")
|
||||||
|
dofile(minetest.get_modpath("circuits") .. "/circuits.lua")
|
||||||
|
dofile(minetest.get_modpath("circuits") .. "/blocks/circuit.lua")
|
||||||
|
dofile(minetest.get_modpath("circuits") .. "/blocks/component.lua")
|
||||||
|
dofile(minetest.get_modpath("circuits") .. "/blocks/cable.lua")
|
||||||
|
dofile(minetest.get_modpath("circuits") .. "/items.lua")
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
player:hud_set_hotbar_itemcount(24)
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_node("circuits:inputBlock", {
|
||||||
|
description = "Input Block",
|
||||||
|
tiles = {"input_block.png"},
|
||||||
|
after_place_node = function(pos, placer)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("formspec",circuits.setNameFormspec("Input Block"),meta:get_string("name"))
|
||||||
|
end,
|
||||||
|
on_receive_fields = function(pos, formname, fields, player)
|
||||||
|
if fields.quit then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.get_meta(pos):set_string("name",fields.name)
|
||||||
|
end,
|
||||||
|
groups = {circuitry = 1,dig_immediate = 3}
|
||||||
|
})
|
||||||
|
minetest.register_node("circuits:outputBlock", {
|
||||||
|
description = "Output Block",
|
||||||
|
tiles = {"output_block.png"},
|
||||||
|
after_place_node = function(pos, placer)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("formspec",circuits.setNameFormspec("Output Block"),meta:get_string("name"))
|
||||||
|
end,
|
||||||
|
on_receive_fields = function(pos, formname, fields, player)
|
||||||
|
if fields.quit then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.get_meta(pos):set_string("name",fields.name)
|
||||||
|
end,
|
||||||
|
groups = {circuitry = 1,dig_immediate = 3}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("Circuits loaded")
|
||||||
|
|
||||||
|
|
||||||
60
items.lua
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
minetest.register_craftitem("circuits:rotator", {
|
||||||
|
description = "The rotator",
|
||||||
|
inventory_image = "rotator.png",
|
||||||
|
on_place = function(itemstack, user, pointed_thing)
|
||||||
|
local node = minetest.get_node(pointed_thing.under)
|
||||||
|
if not string.startsWith(node.name,"circuits:cable_")
|
||||||
|
then return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
local new = circuits.rotateCable(string.without(node.name,"circuits:cable_"),1)
|
||||||
|
minetest.swap_node(pointed_thing.under, {name = "circuits:cable_" .. new})
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
})
|
||||||
|
minetest.register_craftitem("circuits:linker", {
|
||||||
|
description = "The linker",
|
||||||
|
inventory_image = "linker.png",
|
||||||
|
on_place = function(itemstack, user, pointed_thing)
|
||||||
|
local node = minetest.get_node(pointed_thing.under)
|
||||||
|
if not string.startsWith(node.name,"circuits:cable_")
|
||||||
|
then return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
local index = circuits.lookingAtNbIndex(user,pointed_thing.under)
|
||||||
|
|
||||||
|
-- We check if we clicked the last selected node
|
||||||
|
local meta = minetest.get_meta(pointed_thing.under)
|
||||||
|
if meta:get_int("circuits:last_selected_nb") ~= 0
|
||||||
|
then
|
||||||
|
-- We connect
|
||||||
|
local firsti = meta:get_int("circuits:last_selected_nb")
|
||||||
|
local new = circuits.connectInCable(string.without(node.name,"circuits:cable_"),firsti,index)
|
||||||
|
minetest.swap_node(pointed_thing.under, {name = "circuits:cable_" .. new})
|
||||||
|
|
||||||
|
-- We destroy the saved selected nb
|
||||||
|
meta:set_int("circuits:last_selected_nb",0)
|
||||||
|
else
|
||||||
|
-- We save the selected nb
|
||||||
|
meta:set_int("circuits:last_selected_nb",index)
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
})
|
||||||
|
minetest.register_craftitem("circuits:unlinker", {
|
||||||
|
description = "The unlinker",
|
||||||
|
inventory_image = "unlinker.png",
|
||||||
|
on_place = function(itemstack, user, pointed_thing)
|
||||||
|
local node = minetest.get_node(pointed_thing.under)
|
||||||
|
if not string.startsWith(node.name,"circuits:cable_")
|
||||||
|
then return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
local index = circuits.lookingAtNbIndex(user,pointed_thing.under)
|
||||||
|
|
||||||
|
local new = circuits.disconnectInCable(string.without(node.name,"circuits:cable_"),index)
|
||||||
|
minetest.swap_node(pointed_thing.under, {name = "circuits:cable_" .. new})
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
})
|
||||||
3
mod.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
name=logikraft
|
||||||
|
description=Logical circuitry in Minetest
|
||||||
|
depends=default
|
||||||
BIN
textures/cable_gray.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
textures/circuit_block.png
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
textures/component.png
Normal file
|
After Width: | Height: | Size: 596 B |
BIN
textures/component22_side.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
textures/component22_top.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
textures/input_block.png
Normal file
|
After Width: | Height: | Size: 606 B |
BIN
textures/linker.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
textures/output_block.png
Normal file
|
After Width: | Height: | Size: 636 B |
BIN
textures/rotator.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
textures/unlinker.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
82
utils.lua
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
function table.indexof(arr,x)
|
||||||
|
for i,v in ipairs(arr)
|
||||||
|
do
|
||||||
|
if v == x
|
||||||
|
then return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function table.arrperm(arr1,arr2)
|
||||||
|
out = {}
|
||||||
|
for i,v in ipairs(arr1)
|
||||||
|
do
|
||||||
|
table.insert(out,table.indexof(arr2,v))
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
function table.invert(arr)
|
||||||
|
out = {}
|
||||||
|
for k,v in pairs(arr)
|
||||||
|
do
|
||||||
|
out[v] = k
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
function table.getkey1(arr,x)
|
||||||
|
for k,v in pairs(arr)
|
||||||
|
do
|
||||||
|
if table.equals1(x,v)
|
||||||
|
then return k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function string.startsWith(str,ex)
|
||||||
|
return string.sub(str,1,string.len(ex)) == ex
|
||||||
|
end
|
||||||
|
function string.without(str,ex)
|
||||||
|
return string.sub(str,string.len(ex)+1,-1)
|
||||||
|
end
|
||||||
|
function table.equals1(arr1,arr2)
|
||||||
|
for i,v in ipairs(arr1)
|
||||||
|
do
|
||||||
|
if arr2[i] ~= v
|
||||||
|
then return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return #arr1 == #arr2
|
||||||
|
end
|
||||||
|
|
||||||
|
local function nodeboxDistance(nb,p)
|
||||||
|
return
|
||||||
|
(((nb[1] < p[1]) and (p[1] - nb[1])) or ((p[1] < nb[4]) and (nb[4] - p[1])) or 0) +
|
||||||
|
(((nb[2] < p[2]) and (p[2] - nb[2])) or ((p[2] < nb[5]) and (nb[5] - p[2])) or 0) +
|
||||||
|
(((nb[3] < p[3]) and (p[3] - nb[3])) or ((p[3] < nb[6]) and (nb[6] - p[3])) or 0)
|
||||||
|
end
|
||||||
|
function circuits.nearestNodeboxIndex(nodeboxes,point)
|
||||||
|
local minindex=-1
|
||||||
|
local minvalue = 9999
|
||||||
|
for i,nb in ipairs(nodeboxes)
|
||||||
|
do
|
||||||
|
local d = nodeboxDistance(nb,point)
|
||||||
|
if d < minvalue
|
||||||
|
then
|
||||||
|
minvalue = d
|
||||||
|
minindex = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return minindex
|
||||||
|
end
|
||||||
|
|
||||||
|
function circuits.lookingAtNbIndex(user,under)
|
||||||
|
local range=5
|
||||||
|
local eye = vector.add(user:get_pos(),{x=0,y=1.625,z=0})
|
||||||
|
local objective = vector.add(eye, vector.multiply(user:get_look_dir(),range))
|
||||||
|
local ray = minetest.raycast(eye,objective,false,false)
|
||||||
|
for p in ray
|
||||||
|
do
|
||||||
|
if p.under.x==under.x and p.under.y==under.y and p.under.z==under.z
|
||||||
|
then return p.box_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||