Logikraft/blocks/cable.lua
2024-05-20 19:56:30 +02:00

240 lines
7.3 KiB
Lua

--[[
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
--]]
logikraft.cablenodes = {}
logikraft.cables = {}
function logikraft.registerCable(name,nodeboxes,connections,nbconn)
local nodename = "logikraft:cable_"..name
minetest.register_node(nodename, {
tiles = {
"cable_gray.png",
"cable_gray.png",
"cable_gray.png",
"cable_gray.png",
"cable_gray.png",
"cable_gray.png",
},
paramtype = "light",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = nodeboxes
},
groups = {circuitry = 1,dig_immediate = 3},
drop = nil
})
-- 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
logikraft.cablenodes[nodename] = name
logikraft.cables[name] = {
nbs = nodeboxes,
conns = connections2,
nbToConn = nbconn2
}
end
function logikraft.cableFromConns(conns)
for name,cable in pairs(logikraft.cables)
do
if table.equals1(conns,cable.conns)
then return name
end
end
return nil
end
function logikraft.rotateCable(name,r)
local conn = logikraft.cables[name].conns
local newconn = {}
for i,v in ipairs(conn)
do
newconn[i] = logikraft.rotate4dir(v,r)
end
table.sort(newconn)
return logikraft.cableFromConns(newconn)
end
function logikraft.connectInCable(name,a,b)
local conns = table.copy(logikraft.cables[name].conns)
local cia = logikraft.cables[name].nbToConn[a]
local cib = logikraft.cables[name].nbToConn[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 logikraft.cableFromConns(conns)
end
function logikraft.connFromDir(name,dir)
local conns = logikraft.cables[name].conns
local dir8 = math.pow(2,dir)
for i,c in ipairs(conns)
do
if (math.fmod(c,2*dir8) - dir8 >= 0)
then
return i
end
end
return nil
end
--[[
Returns {newcablea,newcableb} if the two cables are contiguous
Returns nil otherwise
If namea or nameb is nil, no cable is present, and we create a single pin, or we connect to the conn in the direction
If a or b is nil, we consider that
--]]
function logikraft.connectContiguousCable(namea,posa,a,nameb,posb,b)
print("Connecting "..tostring(namea).."("..tostring(a)..") with "..tostring(nameb).."("..tostring(b)..")")
local dira = (posa.y == posb.y) and (
(posa.z + 1 == posb.z and posa.x == posb.x and 3) or
(posa.x + 1 == posb.x and posa.z == posb.z and 2) or
(posa.z - 1 == posb.z and posa.x == posb.x and 1) or
(posa.x - 1 == posb.x and posa.z == posb.z and 0) or
nil) or nil
if dira == nil
then return nil
end
if not namea
then
namea = logikraft.cableFromConns({logikraft.rotate4dir(4,6-dira)})
a = 1 -- There is only one nodebox
end
if not nameb
then
nameb = logikraft.cableFromConns({logikraft.rotate4dir(4,4-dira)})
b = 1 -- There is only one nodebox
end
local cia
if not a
then
cia = logikraft.connFromDir(namea,dira)
if not cia
then
-- We need to add a tip to a
local connsa = table.copy(logikraft.cables[namea].conns)
table.insert(connsa,logikraft.rotate4dir(4,6-dira))
table.sort(connsa)
namea = logikraft.cableFromConns(connsa)
cia = logikraft.connFromDir(namea,dira)
end
else
cia = logikraft.cables[namea].nbToConn[a]
end
local cib
if not b
then
cib = logikraft.connFromDir(nameb,math.fmod(dira+2,4))
if not cib
then
-- We need to add a tip to b
local connsb = table.copy(logikraft.cables[nameb].conns)
table.insert(connsb,logikraft.rotate4dir(4,4-dira))
table.sort(connsb)
nameb = logikraft.cableFromConns(connsb)
cib = logikraft.connFromDir(nameb,math.fmod(dira+2,4))
end
else
cib = logikraft.cables[nameb].nbToConn[b]
end
print(dira)
print(namea)
print(cia)
print(nameb)
print(cib)
local connsa = table.copy(logikraft.cables[namea].conns)
local connsb = table.copy(logikraft.cables[nameb].conns)
--print(dump(connsa))
--print(dump(connsb))
local cia2 = logikraft.connFromDir(namea,dira)
local cib2 = logikraft.connFromDir(nameb,math.fmod(dira+2,4))
-- (nba == nil) -> Need to add dira to the a
-- (a == nba) -> Already connected
-- (a ~= nba) -> Need to connect a and nbas
if (cia2 == nil)
then
connsa[cia] = connsa[cia] + math.pow(2,dira)
elseif (cia ~= cia2)
then
-- We take the v size of selected cable
local v = math.fmod(math.floor(connsa[cia]/16),2)
connsa[cia] = math.fmod(connsa[cia],16) + math.fmod(connsa[cia2],16) + v*16
table.remove(connsa,cia2)
end
if (cib2 == nil)
then
connsb[cib] = connsb[cib] + math.pow(2,math.fmod(dira+2,4))
elseif (cib ~= cib2)
then
-- We take the v size of selected cable
local v = math.fmod(math.floor(connsb[cib]/16),2)
connsb[cib] = math.fmod(connsb[cib],16) + math.fmod(connsb[cib2],16) + v*16
table.remove(connsb,cib2)
end
table.sort(connsa)
table.sort(connsb)
return {logikraft.cableFromConns(connsa),logikraft.cableFromConns(connsb)}
end
function logikraft.disconnectInCable(name,a)
local conns = table.copy(logikraft.cables[name].conns)
local cindex = logikraft.cables[name].nbToConn[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 logikraft.cableFromConns(conns)
end
function logikraft.resizeInCable(name,a)
local conns = table.copy(logikraft.cables[name].conns)
local cindex = logikraft.cables[name].nbToConn[a]
conns[cindex] = (conns[cindex] >= 16) and (conns[cindex] - 16) or (conns[cindex] + 16)
table.sort(conns)
return logikraft.cableFromConns(conns)
end