From 7524c13e7a1f72419b3f282f8a88b4f274c52b10 Mon Sep 17 00:00:00 2001 From: Samy Avrillon Date: Wed, 15 May 2024 21:02:40 +0200 Subject: [PATCH] First commit, workinging sample --- .luacheckrc | 45 ++++ blocks/cable.lua | 388 ++++++++++++++++++++++++++++++++++ blocks/circuit.lua | 39 ++++ blocks/component.lua | 126 +++++++++++ circuits.lua | 57 +++++ init.lua | 53 +++++ items.lua | 60 ++++++ mod.conf | 3 + textures/cable_gray.png | Bin 0 -> 4343 bytes textures/circuit_block.png | Bin 0 -> 680 bytes textures/component.png | Bin 0 -> 596 bytes textures/component22_side.png | Bin 0 -> 4559 bytes textures/component22_top.png | Bin 0 -> 4571 bytes textures/input_block.png | Bin 0 -> 606 bytes textures/linker.png | Bin 0 -> 4355 bytes textures/output_block.png | Bin 0 -> 636 bytes textures/rotator.png | Bin 0 -> 4382 bytes textures/unlinker.png | Bin 0 -> 4378 bytes utils.lua | 82 +++++++ 19 files changed, 853 insertions(+) create mode 100644 .luacheckrc create mode 100644 blocks/cable.lua create mode 100644 blocks/circuit.lua create mode 100644 blocks/component.lua create mode 100644 circuits.lua create mode 100644 init.lua create mode 100644 items.lua create mode 100644 mod.conf create mode 100644 textures/cable_gray.png create mode 100644 textures/circuit_block.png create mode 100644 textures/component.png create mode 100644 textures/component22_side.png create mode 100644 textures/component22_top.png create mode 100644 textures/input_block.png create mode 100644 textures/linker.png create mode 100644 textures/output_block.png create mode 100644 textures/rotator.png create mode 100644 textures/unlinker.png create mode 100644 utils.lua diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..07485c1 --- /dev/null +++ b/.luacheckrc @@ -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" + } + }, +} \ No newline at end of file diff --git a/blocks/cable.lua b/blocks/cable.lua new file mode 100644 index 0000000..de7445a --- /dev/null +++ b/blocks/cable.lua @@ -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 \ No newline at end of file diff --git a/blocks/circuit.lua b/blocks/circuit.lua new file mode 100644 index 0000000..ca6180d --- /dev/null +++ b/blocks/circuit.lua @@ -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} +}) \ No newline at end of file diff --git a/blocks/component.lua b/blocks/component.lua new file mode 100644 index 0000000..eb4fe1b --- /dev/null +++ b/blocks/component.lua @@ -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=0 and z<0 and -z>=x and 6 or + x>=0 and z<0 and -zJSu!KNSIki$``VJjD@>l2-SH{Avt>{4{-dXj6*q`PEx(;|wERe7cKpYy zE$4q}3zSFv^UC4w$e;d$X-XAql)T3Ib6eIrp4)N8;`SH$>MpIJ5OSFP62RnYZ6I!tQ_JzBg0-Lui+Hg|VY&rXJ+o-4} zm!tn~Z4tbtTNE$6cIUc%st3&7{YAf|HN0DuRh%n(e2cc|*M%hyJ}2_O^f>)-QcFGa zVulYnD(Q>;?DyTu{}ev&l)@|f3N7})`wZqY+cJdu@)#HxTQZ%U13aCbVFAU!P%)== zqOHea2brVs!QP=!GH(FO$zE!q{Z@Cw&js~IuBSbe1?iHN%&-1^|b@uaH< zk4A>GhdT=VVJIvs2r8K<^nbcY)RBsUJN@O~<;vePER0NDbyJu<FfP`kH1V} zs;8oz`aFXdO-K4;rpMMjjwyA9@%H`W+wNL1{yBeO>a~y8XB~K> z{<61E%$A95TVwa@KDGCZ)2$C&n5-u`N%?0c*HNVpb#C{ku(Rbi{xjXa{hOVie1lHu z)Lo2xe2pK4QrB1S*}Z-D_WJW%e*b1{&MaDcqmHYIfq}OoGbExU!q>+tIX_n~F(p4K zRj(qqfB^(->?;Zqle1Gx6p~WYGxKbf-tXS8q>!0ns}yePYv5bpoSKp8QB{;0T;&&% zT$P<{nWAKG$7NGtRgqhen_7~nP?4LHS8P>bs{}UJDzDfIB&@Hb09I0xZL1XF8=&Bv zUzDm~qGzIKpzB(ZS!SeU$E9FXl#*r@+442g6AGjj{T zx+-!DP*j#=rXd0g#Wx@suy>FhQjuE#Hy1@U%b3&@4^YEY-vy#n{l;AjQNIY*b3J zm0NyMZeoe8Qf6*qda8awUOHF;6yR2l0iL!>MtTri!6E@Ui6v?IMY*<0KACx?6$qsv znYpRKC5fQWG&DCfH8L|aGcYzcv@o@VSOnG`mReMtnV$zT)6hWA*aWN{6fIW%MVYC2 zC5fPPYO7=j7O%)HuyQU+O)SYT3dzsUu~h;Yp-6Dmf!DFFiHIRtcJ1VOlb=Bn5MeG{ZDA zOB3DHG~*Oq6H6l_-9%$ULtXO}vs6=qWW$s+^E6b`i}TY;$`gxH9n(|uN^F(fGjj{T zVWpq}jwnr3)#Vwfpja?4GSM|K)kOrDF*LyRAzrl62bCExAKU0-gb73eQXylEkDFjGTJes;jgNvjPAW89P z>Y`e3aUr@>sd*{3O65xScAFkwD`H?^;4JWnEM{QPQwCwiilz2t3=9nHC7!;n>@Qe3 zc@@Q5_J26Uz`)>G;u=xnoSzG7gEKe>xjKgU2U#hkr|4!Cq^2vB8R{7*Xp|Ob=A|om zdbulj1-QB^lvx;P>L?VJCgx<8R4UjiSXy$enU*+(fq{X?)5S4_<9hOonOoQxm@61h U@7t5*1nTyAy85}Sb4q9e05Q5CO#lD@ literal 0 HcmV?d00001 diff --git a/textures/circuit_block.png b/textures/circuit_block.png new file mode 100644 index 0000000000000000000000000000000000000000..f352a874dc60dd9f86182617d415fcab4a9e2314 GIT binary patch literal 680 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLTQZ%U13aCb6$*;-(=u~X z85lGs)=sqbI2<6->L1*#6v}ShVUe=JPt3(tCR?;CK=BIKTB{j*zVOd7QPI@vYsx-& zaQ@L%&E1>V@vUo8_`&?>&4VQ`lvM9c7l}Gj@$jSFx!un{+^cQ4u)^T%t1jkQd9z=p zIGuSGcJy6%i-3c@n!uEqsb@Tcxb}T5_1_y(ZaDAh{qN~tS5|g2GETHO$8%Zjp2EDF zTX@g?J|Y-4DfChCqr%C09)C`h9(`qmiqxM7*B&r}g2UeVfjdMk#wF33^XZaB}2L4M|XT+wIrYYBE>7=Fj1E z@k-O3))`4yiUqW?-Td18|KR(ZQLQUI^)=@(IO+F&HsmUK&vbUz;~IHuzt1cjcFf^b zx8rjeHqT#j{dUwB4v8CVdh2e_+Qc67j=|Z#E$7raktM1kTnBzj)&}!Q>|w3CzGvsw zbA`VcQZm9;N7pQuB8T(Eg+1C0a^G*uZEw(hVz;C6G>fhMoDM~{ z0+*JVwd;OICO&6P{FlgZAnjSK_4@guF;C}xjI7i+n5J&$_=)dU(!tg3S+O5x2UI?I zi3Nst)0I*yuHV=;Rw*aIb|jT0|SGntDnm{r-UW|4)G>f literal 0 HcmV?d00001 diff --git a/textures/component.png b/textures/component.png new file mode 100644 index 0000000000000000000000000000000000000000..1482418f78de78d1fe2923ed850e547204c8ec4b GIT binary patch literal 596 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLTQZ%U13aCb6$*;-(=u~X z85lGs)=sqbI2<6->L2Xws>PQkP?wdtQk3v=lv~Vp9%eZ>*$R+dk^T zL1x>vTH^(s7?jckgJ*=!p8Qm#=Jo4&RV&{m*__`0{`{-!pTwA%gbL?e^_gAKTv2s- zUEw`-u}II09p^ib`|eWssC+%N|GtHItXRdejI>Lik0@;nd6TrYJM!d}&gC78XXOR# zoA5Q_@t&iR>#s!qp7*D9;+~D0&Xh(edn5^ZPf&Dpl}!yvPSH0%X;dSw9 z)4kRiNmz;nwDKMO+Wi0E`Eh#za%ZITgAeY!z_MX*7q*6UU|d9<+GBs)`=`p72!JYTe3EoPht=2uWNgDZarW4 ziyLEmN@-Tvx+XAEZzkx!g~fx*tx#W6(VeDar1=h78eHy9WgaBy%4t^9Sk{kx99w5BE@$E*Bucajql v5|R`Id$J@nr6ML==G-V{S5x7?hnFF*g=gkhr8}(*3=9mOu6{1-oD!Mfq~&&RY*ihP-3}4K~a8M zW=^U?No7H*LTW{38UsVct=_=sJXS@HzvZH_O#1RV$1CqFv3~KX+U=v?a?i<0E*1(h zhI8ZRum4imY2rC8TRV=+@yyw!hcir4rDvUNlT#9G`hP%peFH<#9IM!PbH4{0ENlAJ z_IwIom|D<2^}WOU#(e*p?xst1;#_Q}HXF+pDsru4QJ(!zuBU7JuZmk6F9+Y+>$`eN z%nqq7oL8e{%7iy{RmzE9ysl@*_0;l$`G!AJwH~M}-z2nUmG88w+{=B&{JNZ-*IzZT z&YJrC`U7o8#xu53rB(c&pXa=j{HyrCGVB+dkXhM+jF5N(1_s8~OlRi+PiJSC&lwmh z=G0EK_Bb3M()NGbw5|{t9i>MT7IHPk);x?@9niwHFf8Nh!6(b~GcHY7vcrOF9V@$h zcPP7fdaP^=tK$d8M{gc1d7-2_Z?;I(k%|XJ_W!E?&96Ss`lpvG`0P511zFQ3`l+?# z9KW>V@htEH&%92v-Ouz6zh`JDL2rT)cPn=7!qiD>U(-@ zm_>eJn6~M)UF!9T7VFpQ6wke8Fe&1QkPF9zKxawOh>nZvCMGHQKIi2BKjE?XN!7`# zdEEL~Ll!y}{drLTp?X_dV$mUAF7<{7-MRHW3=3lyL~eikKKXXuJch>f2VU8~SMw%( zoBX9Jx?7I1_V$6JrO}hWH=LGD_~1F6=j24DEq_{>KGeD0pThhrzj2;vdEVOMId%+^ zvqE37Sy-^Rbx+y*?&G_6=XU{&S*5rx{*6yvxAA7o8arQ4-ZxN)4{^ z3rViZPPR-@vbW>1sj#ZZEyztRNmQuF&B-gas<2f8n`@Ot;j4hQnKSxuqjGOvkG!?gBnqkl4h%vQBqQ1rLSLJUanVete0Pu zu5V~*X{m2uq;F)TTa=QfTU?n}l31aeSF8*&0%C?sYH@N=W(tB0+w{vfnBt zKRGkS3d~GRNlP;~N;T3oO*S;vHLBAW{Op^QIe^dg=MmCQet9?u1RW&fo`HnvXQQ3nz5m=xv`14abhZx5&lJ) z>6v+nImoU88I_WmVwGfMo}8MTXrOConqsDFl4M}4o0x2ztZQhRY-yTmWR_@XWCAuS zCE3a?zbH4c#8xRYH!(d`zaTFiECC8|E5`s&TO}hs1B6IGPGU(~eo?Nil22w{X$3+e zBr`WPxFiu2nug|vCT0f4#>R#g1{Nkp76?UQsYS(^`FS8S4Gr{+Ax;2Ai{b~ z$i&LP)XKmp#K6GH#K_9fP}{)B$^c1yeoAIqB_Y*zpv++diE@w3;*$KLO0WX@FIS7NK=o|#(! z4l4x>a71aMsxHq+1;v7ak%_K>sjh)xh>@|Ck(rf&DKx*?y}vd$@?2>>>2 BM1%kU literal 0 HcmV?d00001 diff --git a/textures/component22_top.png b/textures/component22_top.png new file mode 100644 index 0000000000000000000000000000000000000000..37a55c22b056ca0662e44828aff0f9cd3bee4dc8 GIT binary patch literal 4571 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 GGywo_<@uEW literal 0 HcmV?d00001 diff --git a/textures/linker.png b/textures/linker.png new file mode 100644 index 0000000000000000000000000000000000000000..7425b8d3e38ba22a6a1f13edd6a7d1601f92bc65 GIT binary patch literal 4355 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7-c^M}lmsP~D-;yvr)B1( zDwI?fq$;FVWTr7NRNU$fyxn`mfa6cOXgCwwp9M0{Rb$zs|Mex$i3y8(+0m0&kYL02 z`}KDY`@1`eE`(%lo5Q(m*)d+nrHQ9sD!+VbyHL{RLxHHogoNo6rL6ZcyUW;`%L_gK zdGp1rD*{V*Uzqjyv~c_$#p~zY&N)1q;WPXHgWi_86Z>jP-EL-8#^gr7%={Xs)mnUN zqsAVisgrmMQ!g>uZuk2Var2y8CPx*c@qBm5ITh12So9Y)Fa5Ig(gyV(8Zy5eYj_>> zJC+1j913n?nlYO{tEBU1`0VJ#`rqbfx0;K6EL)p=CzFMNfw4K$**U<|*%{_@28N0` zwG(YU4m-#kjSuct(&bANC_E7`SEs4V;+mGoLZ=m?QKbeuzi`jmqN1tS*OYzmVE@ro z&E1>V@vUo8_`&$-&4VQ`lvMxeYi{ZI_+W?p`**hQ?lC%TK2)+=o$p0k?y||8nzN&) zR>ccCNhqla1kMPZJ^86f&GGBDOf`GEKkEE1uJ7xZwp~JCLdWAZX}69@A2FU?*8ACR z;|Z@Ww;Dg2yi2T|@;ld6{W-St#ij$suEvw+sf%?kO%h)nd&X;-pN+4~)sp5uIgn@y#A~PhSB*NFnDmgz_FEJ%Q zDOIl`w}1fzZ0suv5|gu2OB9k)(=+pImEP~(ucVNfVyhHx>TBRz;GCL~=}}db8eHWU zl3bOYY?-2DZ^va*VO5b^kegbPs8ErclUHn2VXFi-*D9~r3M8zrqySb@l5MLL;Txdf zoL`ixV4`QDXQ1m^ky&P>WXGjoQ-9F1v$^t#a0Pqzg0?p za%PGZn3-46f5J@WYeVNL?c}j6Jrxylhi~@-6R9cG+m>V6f*;Z#I)qZRC6RF{EITv zGxHL2kX;2bDkU?;%E;WrBF)s&L^shW%}CcIG1*u*$ZG(LYxDV_DwBGOi3(BbV)2pwN)}Q zFfy?+Ftsu?3NbRWGBvR>Hq|yTvNAwYpP!PMR!K;;9Vm0yK%(3uv$!O`s1hs$$x*?n zg%BQuo0ADrt)QR)&Jk=(!j*h z&{EgZI5kbzB+=MZ*V4ksQa8!S#3a$!z`)4V0+JNqrWfa@m6RtIr8=gk=9Sngxo74U zfWt~b0~}GBsBS6GNCm}$fsu)>fvGNLfaycLXrm7*GhjZp(Z>iAhytWS#*Rw?A{ON0 zX2)ft4=(9Ir5?mUP^m*p42=s~TA`pYY6(fzwir7xFfgzsdAqwX{Ac*jz|gzjLym!gfwRCPvY3HEPZ@+6 zE0)@qF)%Q&mw5WRvcF*E5iwJ4S@=SSfq_A?#5JPCIX@TFDrW#U7E@Cc$}>wc6hMu| z@J2py1_p*WPZ!4!i_=>tZWKM>z~OZ9=#0B3JyO%(y_^|v^MN}Ho08_FL%o+gf`n8Y z86Mna6->@S+Z|pKc`yC`x*Y9-k#m2duChibk%L~p}I3> b*k5F3N%lRz>D9#rpf01QtDnm{r-UW|R%j{d literal 0 HcmV?d00001 diff --git a/textures/output_block.png b/textures/output_block.png new file mode 100644 index 0000000000000000000000000000000000000000..2420f142cb48a362a8bf8a0848b982e4de50f067 GIT binary patch literal 636 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLn=_rA13aCb6$*;-(=u~X z85lGs)=sqbIP4&EH2$)eYn05H1&byuw7Ti)Dw8eR6`**9YpvCc{yN9WZ7N5P1{UaA z{MZ;#T2OfH>cLO}7JG*|vU5aYmmK-8+A3x!C-eRB-Mz=}S~p~eiJs+BW$@j8)<;Y8 z$*0v$KSULKn%qU4CnZT1FPhQz{>Lu&hPCB|)1KD9J1-c@J&lQlZLi2_FXOuWTa$j~@Zoi@4&NCZ*?wv_{)>)af@XFC5aqZM#<#}p-D`)xr zj5(J)^`ltw+Nkhb-&6E^M7~T-U3OW+#ZxlwUJA9Dbamo5$ zl<=V2Sw}>HAX7IMN1WY*F~`0JO5(#rvnFcFKmDI_1eAT zFPSGSU3ba+z(GZWxJ7SD=a+vk`~L0y%(8m>#-O4#Yo^TMW?*38EbxddW?;}$24TjE zrS@eE3=Hfgp1!W^FIZ$nM0t&+yH7AMFi4iTMwB?`=jNv7l`uFLr6!i7rYMwWmSiZn zd-?{1H}Z)yFfgQhx;TbtoKMct;!ajz-C$r~aKuGub^6Iqp*}n+OkyVgdiFMDC`q1s zKXIqekI-bUO$lBK(wu^GHiir6ooKnwm=U8R#liF|+ksp7OhK~aH+dVM4=pUh{|pX_ nq#V@uW%b|ea7p2#6vLx@mHb%eZ=V?$7#KWV{an^LB{Ts5AnpYG literal 0 HcmV?d00001 diff --git a/textures/rotator.png b/textures/rotator.png new file mode 100644 index 0000000000000000000000000000000000000000..dbf519a5ccba473035962e43143988193d1fbbc2 GIT binary patch literal 4382 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 literal 0 HcmV?d00001 diff --git a/utils.lua b/utils.lua new file mode 100644 index 0000000..72f2dde --- /dev/null +++ b/utils.lua @@ -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 \ No newline at end of file