local explode_port_states = function(state) local port = {} port.a = state%2 == 1 port.b = state%4 >= 2 port.c = state%8 >= 4 port.d = state%16 >= 8 return port end local implode_port_states = function(port) local state = 0 if port.a then state = state + 1 end if port.b then state = state + 2 end if port.c then state = state + 4 end if port.d then state = state + 8 end return state end local gettiles = function(state) local tiles = { "digistuff_ioexp_top.png", "jeija_microcontroller_bottom.png", "jeija_microcontroller_sides.png", "jeija_microcontroller_sides.png", "jeija_microcontroller_sides.png", "jeija_microcontroller_sides.png" } local port = explode_port_states(state) for p,v in pairs(port) do if v then tiles[1] = tiles[1].."^jeija_luacontroller_LED_"..string.upper(p)..".png" end end return tiles end local ioexp_get_on_rules = function(state) local port = explode_port_states(state) local rules = {} if port.a then table.insert(rules,vector.new(-1,0,0)) end if port.b then table.insert(rules,vector.new(0,0,1)) end if port.c then table.insert(rules,vector.new(1,0,0)) end if port.d then table.insert(rules,vector.new(0,0,-1)) end return rules end local ioexp_get_off_rules = function(state) local port = explode_port_states(state) local rules = {} if not port.a then table.insert(rules,vector.new(-1,0,0)) end if not port.b then table.insert(rules,vector.new(0,0,1)) end if not port.c then table.insert(rules,vector.new(1,0,0)) end if not port.d then table.insert(rules,vector.new(0,0,-1)) end return rules end local ioexp_digiline_send = function(pos) local meta = minetest.get_meta(pos) local channel = meta:get_string("channel") local port = { a = meta:get_int("aon") == 1, b = meta:get_int("bon") == 1, c = meta:get_int("con") == 1, d = meta:get_int("don") == 1, } local outstate = explode_port_states(meta:get_int("outstate")) for k,v in pairs(outstate) do port[k] = port[k] or v end digiline:receptor_send(pos,digiline.rules.default,channel,port) end local ioexp_handle_digilines = function(pos,node,channel,msg) local meta = minetest.get_meta(pos) if channel ~= meta:get_string("channel") then return end if msg == "GET" then ioexp_digiline_send(pos) return end if type(msg) ~= "table" then return end local state = implode_port_states(msg) node.name = "digistuff:ioexpander_"..state meta:set_int("outstate",state) minetest.swap_node(pos,node) for _,i in ipairs(ioexp_get_on_rules(state)) do mesecon.receptor_on(pos,{i}) end for _,i in ipairs(ioexp_get_off_rules(state)) do mesecon.receptor_off(pos,{i}) end end local ioexp_rule_to_port = function(rule) if rule.x < 0 then return "a" elseif rule.z > 0 then return "b" elseif rule.x > 0 then return "c" elseif rule.z < 0 then return "d" end end local ioexp_handle_mesecons = function(pos,_,rule,state) local meta = minetest.get_meta(pos) local port = ioexp_rule_to_port(rule) if not port then return end local meta = minetest.get_meta(pos) meta:set_int(port.."on",state == "on" and 1 or 0) ioexp_digiline_send(pos) end for i=0,15,1 do local offstate = i == 0 minetest.register_node("digistuff:ioexpander_"..i, { description = offstate and "Digilines I/O Expander" or string.format("Digilines I/O Expander (on state %X - you hacker you!)",i), groups = offstate and {cracky = 3,} or {cracky = 3,not_in_creative_inventory = 1,}, on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec","field[channel;Channel;${channel}") meta:set_int("aon",0) meta:set_int("bon",0) meta:set_int("con",0) meta:set_int("don",0) meta:set_int("outstate",i) end, _digistuff_channelcopier_fieldname = "channel", tiles = gettiles(i), inventory_image = "digistuff_ioexp_top.png", drawtype = "nodebox", drop = "digistuff:ioexpander_0", selection_box = { --From luacontroller type = "fixed", fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, }, node_box = { --From Luacontroller type = "fixed", fixed = { {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab {-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board {-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC } }, paramtype = "light", sunlight_propagates = true, on_receive_fields = function(pos, formname, fields, sender) local name = sender:get_player_name() if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then minetest.record_protection_violation(pos,name) return end local meta = minetest.get_meta(pos) if fields.channel then meta:set_string("channel",fields.channel) end end, mesecons = { effector = { rules = ioexp_get_off_rules(i), action_change = ioexp_handle_mesecons, }, receptor = { state = mesecon.state.on, rules = ioexp_get_on_rules(i), }, }, digiline = { receptor = {}, effector = { action = ioexp_handle_digilines, }, }, }) end