summaryrefslogtreecommitdiff
path: root/mesecons_luacontroller
diff options
context:
space:
mode:
authorJeija <jeija@mesecons.net>2014-11-25 17:20:05 +0100
committerJeija <jeija@mesecons.net>2014-11-25 17:36:52 +0100
commit4bd9d2a9ec84347e7c7ee488664120e39643a013 (patch)
treee5cc0f1ade32798fb5aab0d5b5f020c84e4e0a98 /mesecons_luacontroller
parentf69caba03674d04be960344baea308159219b081 (diff)
parent085b4d8bb72a95303f6e683cdbf57ed2cddb53b7 (diff)
downloadmesecons-4bd9d2a9ec84347e7c7ee488664120e39643a013.tar
mesecons-4bd9d2a9ec84347e7c7ee488664120e39643a013.tar.gz
mesecons-4bd9d2a9ec84347e7c7ee488664120e39643a013.tar.bz2
mesecons-4bd9d2a9ec84347e7c7ee488664120e39643a013.tar.xz
mesecons-4bd9d2a9ec84347e7c7ee488664120e39643a013.zip
Merge branch 'improve-luacontroller'
However, without the print_count limiting functionality Conflicts: mesecons_luacontroller/init.lua
Diffstat (limited to 'mesecons_luacontroller')
-rw-r--r--mesecons_luacontroller/init.lua737
1 files changed, 395 insertions, 342 deletions
diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua
index 637b2e5..2cbebd6 100644
--- a/mesecons_luacontroller/init.lua
+++ b/mesecons_luacontroller/init.lua
@@ -1,11 +1,21 @@
+-- ______
+-- |
+-- |
+-- | __ ___ _ __ _ _
+-- | | | | | |\ | | |_| | | | | |_ |_|
+-- |___| |______ |__| | \| | | \ |__| |_ |_ |_ |\
+-- |
+-- |
+--
+
-- Reference
--- ports = get_real_portstates(pos): gets if inputs are powered from outside
--- newport = merge_portstates(state1, state2): just does result = state1 or state2 for every port
--- action_setports(pos, rule, state): activates/deactivates the mesecons according to the portstates (helper for action)
--- action(pos, ports): Applies new portstates to a luacontroller at pos
--- lc_update(pos): updates the controller at pos by executing the code
--- reset_meta (pos, code, errmsg): performs a software-reset, installs new code and prints error messages
--- reset (pos): performs a hardware reset, turns off all ports
+-- ports = get_real_port_states(pos): gets if inputs are powered from outside
+-- newport = merge_port_states(state1, state2): just does result = state1 or state2 for every port
+-- set_port(pos, rule, state): activates/deactivates the mesecons according to the port states
+-- set_port_states(pos, ports): Applies new port states to a LuaController at pos
+-- run(pos): runs the code in the controller at pos
+-- reset_meta(pos, code, errmsg): performs a software-reset, installs new code and prints error messages
+-- resetn(pos): performs a hardware reset, turns off all ports
--
-- The Sandbox
-- The whole code of the controller runs in a sandbox,
@@ -20,62 +30,76 @@
local BASENAME = "mesecons_luacontroller:luacontroller"
-local rules = {}
-rules.a = {x = -1, y = 0, z = 0, name="A"}
-rules.b = {x = 0, y = 0, z = 1, name="B"}
-rules.c = {x = 1, y = 0, z = 0, name="C"}
-rules.d = {x = 0, y = 0, z = -1, name="D"}
+local rules = {
+ a = {x = -1, y = 0, z = 0, name="A"},
+ b = {x = 0, y = 0, z = 1, name="B"},
+ c = {x = 1, y = 0, z = 0, name="C"},
+ d = {x = 0, y = 0, z = -1, name="D"},
+}
+
------------------
-- Action stuff --
------------------
--- These helpers are required to set the portstates of the luacontroller
+-- These helpers are required to set the port states of the luacontroller
-function lc_update_real_portstates(pos, rulename, newstate)
+local function update_real_port_states(pos, rule_name, new_state)
local meta = minetest.get_meta(pos)
- if rulename == nil then
+ if rule_name == nil then
meta:set_int("real_portstates", 1)
return
end
local n = meta:get_int("real_portstates") - 1
local L = {}
for i = 1, 4 do
- L[i] = n%2
- n = math.floor(n/2)
+ L[i] = n % 2
+ n = math.floor(n / 2)
end
- if rulename.x == nil then
- for _, rname in ipairs(rulename) do
- local port = ({4, 1, nil, 3, 2})[rname.x+2*rname.z+3]
+ -- (0,-1) (-1,0) (1,0) (0,1)
+ local pos_to_side = { 4, 1, nil, 3, 2 }
+ if rule_name.x == nil then
+ for _, rname in ipairs(rule_name) do
+ local port = pos_to_side[rname.x + (2 * rname.z) + 3]
L[port] = (newstate == "on") and 1 or 0
end
else
- local port = ({4, 1, nil, 3, 2})[rulename.x+2*rulename.z+3]
- L[port] = (newstate == "on") and 1 or 0
+ local port = pos_to_side[rule_name.x + (2 * rule_name.z) + 3]
+ L[port] = (new_state == "on") and 1 or 0
end
- meta:set_int("real_portstates", 1 + L[1] + 2*L[2] + 4*L[3] + 8*L[4])
+ meta:set_int("real_portstates",
+ 1 +
+ 1 * L[1] +
+ 2 * L[2] +
+ 4 * L[3] +
+ 8 * L[4])
end
-local get_real_portstates = function(pos) -- determine if ports are powered (by itself or from outside)
+
+local port_names = {"a", "b", "c", "d"}
+
+local function get_real_port_states(pos)
+ -- Determine if ports are powered (by itself or from outside)
local meta = minetest.get_meta(pos)
local L = {}
local n = meta:get_int("real_portstates") - 1
- for _, index in ipairs({"a", "b", "c", "d"}) do
- L[index] = ((n%2) == 1)
- n = math.floor(n/2)
+ for _, name in ipairs(port_names) do
+ L[name] = ((n % 2) == 1)
+ n = math.floor(n / 2)
end
return L
end
-local merge_portstates = function (ports, vports)
- local npo = {a=false, b=false, c=false, d=false}
- npo.a = vports.a or ports.a
- npo.b = vports.b or ports.b
- npo.c = vports.c or ports.c
- npo.d = vports.d or ports.d
- return npo
+
+local function merge_port_states(ports, vports)
+ return {
+ a = ports.a or vports.a,
+ b = ports.b or vports.b,
+ c = ports.c or vports.c,
+ d = ports.d or vports.d,
+ }
end
-local generate_name = function (ports)
+local function generate_name(ports)
local d = ports.d and 1 or 0
local c = ports.c and 1 or 0
local b = ports.b and 1 or 0
@@ -83,7 +107,8 @@ local generate_name = function (ports)
return BASENAME..d..c..b..a
end
-local setport = function (pos, rule, state)
+
+local function set_port(pos, rule, state)
if state then
mesecon.receptor_on(pos, {rule})
else
@@ -91,83 +116,92 @@ local setport = function (pos, rule, state)
end
end
-local action = function (pos, ports)
+
+local function clean_port_states(ports)
+ ports.a = ports.a and true or false
+ ports.b = ports.b and true or false
+ ports.c = ports.c and true or false
+ ports.d = ports.d and true or false
+end
+
+
+local function set_port_states(pos, ports)
local node = minetest.get_node(pos)
local name = node.name
+ clean_port_states(ports)
local vports = minetest.registered_nodes[name].virtual_portstates
- local newname = generate_name(ports)
-
- if name ~= newname and vports then
- local rules_on = {}
- local rules_off = {}
+ local new_name = generate_name(ports)
- minetest.swap_node(pos, {name = newname, param2 = node.param2})
+ if name ~= new_name and vports then
+ minetest.swap_node(pos, {name = new_name, param2 = node.param2})
- if ports.a ~= vports.a then setport(pos, rules.a, ports.a) end
- if ports.b ~= vports.b then setport(pos, rules.b, ports.b) end
- if ports.c ~= vports.c then setport(pos, rules.c, ports.c) end
- if ports.d ~= vports.d then setport(pos, rules.d, ports.d) end
+ if ports.a ~= vports.a then set_port(pos, rules.a, ports.a) end
+ if ports.b ~= vports.b then set_port(pos, rules.b, ports.b) end
+ if ports.c ~= vports.c then set_port(pos, rules.c, ports.c) end
+ if ports.d ~= vports.d then set_port(pos, rules.d, ports.d) end
end
end
---------------------
--- Overheat stuff --
---------------------
-local overheat_off = function(pos)
+-----------------
+-- Overheating --
+-----------------
+
+local function overheat_off(pos)
mesecon.receptor_off(pos, mesecon.rules.flat)
end
--------------------
--- Parsing stuff --
--------------------
-local code_prohibited = function(code)
- -- Clean code
- local prohibited = {"while", "for", "repeat", "until", "function", "goto"}
- for _, p in ipairs(prohibited) do
- if string.find(code, p) then
- return "Prohibited command: "..p
- end
+local function overheat(pos, meta)
+ if mesecon.do_overheat(pos) then -- If too hot
+ local node = minetest.get_node(pos)
+ node.name = BASENAME.."_burnt"
+ minetest.swap_node(pos, node)
+ -- Wait for pending operations
+ minetest.after(0.2, overheat_off, pos)
+ return true
end
end
-local safe_print = function(param)
+
+-------------------------
+-- Parsing and running --
+-------------------------
+
+local function safe_print(param)
print(dump(param))
end
-deep_copy = function(original, visited) --deep copy that removes functions
- visited = visited or {}
- if visited[original] ~= nil then --already visited this node
- return visited[original]
- end
- if type(original) == 'table' then --nested table
- local copy = {}
- visited[original] = copy
- for key, value in next, original, nil do
- copy[deep_copy(key, visited)] = deep_copy(value, visited)
+minetest.register_globalstep(function(dtime)
+ print_count = print_count - dtime
+end)
+
+
+local function remove_functions(x)
+ local tp = type(x)
+ if tp == "table" then
+ for key, value in pairs(x) do
+ local key_t, val_t = type(key), type(value)
+ if key_t == "function" or val_t == "function" then
+ x[key] = nil
+ else
+ if key_t == "table" then
+ remove_functions(key)
+ end
+ if val_t == "table" then
+ remove_functions(value)
+ end
+ end
end
- setmetatable(copy, deep_copy(getmetatable(original), visited))
- return copy
- elseif type(original) == 'function' then --ignore functions
+ elseif tp == "function" then
return nil
- else --by-value type
- return original
end
+ return x
end
-local safe_serialize = function(value)
- return minetest.serialize(deep_copy(value))
-end
-
-mesecon.queue:add_function("lc_interrupt", function (pos, luac_id, iid)
- -- There is no luacontroller anymore / it has been reprogrammed / replaced
- if (minetest.get_meta(pos):get_int("luac_id") ~= luac_id) then return end
- lc_update(pos, {type="interrupt", iid = iid})
-end)
-
-local getinterrupt = function(pos)
- local interrupt = function (time, iid) -- iid = interrupt id
+local function get_interrupt(pos)
+ -- iid = interrupt id
+ local function interrupt(time, iid)
if type(time) ~= "number" then return end
local luac_id = minetest.get_meta(pos):get_int("luac_id")
mesecon.queue:add_action(pos, "lc_interrupt", {luac_id, iid}, time, iid, 1)
@@ -175,9 +209,9 @@ local getinterrupt = function(pos)
return interrupt
end
-local getdigiline_send = function(pos)
+
+local function get_digiline_send(pos)
if not digiline then return end
- -- Send messages on next serverstep
return function(channel, msg)
minetest.after(0, function()
digiline:receptor_send(pos, digiline.rules.default, channel, msg)
@@ -185,146 +219,186 @@ local getdigiline_send = function(pos)
end
end
-local create_environment = function(pos, mem, event)
+
+local safe_globals = {
+ "assert", "error", "ipairs", "next", "pairs", "pcall", "select",
+ "tonumber", "tostring", "type", "unpack", "_VERSION", "xpcall",
+}
+local function create_environment(pos, mem, event)
-- Gather variables for the environment
local vports = minetest.registered_nodes[minetest.get_node(pos).name].virtual_portstates
- vports = {a = vports.a, b = vports.b, c = vports.c, d = vports.d}
- local rports = get_real_portstates(pos)
-
- return {
- print = safe_print,
- pin = merge_portstates(vports, rports),
- port = vports,
- interrupt = getinterrupt(pos),
- digiline_send = getdigiline_send(pos),
- mem = mem,
- tostring = tostring,
- tonumber = tonumber,
- heat = minetest.get_meta(pos):get_int("heat"),
- -- overheat_max Unit: actions per second, checks are every 1 second
- heat_max = mesecon.setting("overheat_max", 20),
- string = {
- byte = string.byte,
- char = string.char,
- find = string.find,
- format = string.format,
- gmatch = string.gmatch,
- gsub = string.gsub,
- len = string.len,
- lower = string.lower,
- upper = string.upper,
- match = string.match,
- rep = string.rep,
- reverse = string.reverse,
- sub = string.sub,
- },
- math = {
- abs = math.abs,
- acos = math.acos,
- asin = math.asin,
- atan = math.atan,
- atan2 = math.atan2,
- ceil = math.ceil,
- cos = math.cos,
- cosh = math.cosh,
- deg = math.deg,
- exp = math.exp,
- floor = math.floor,
- fmod = math.fmod,
- frexp = math.frexp,
- huge = math.huge,
- ldexp = math.ldexp,
- log = math.log,
- log10 = math.log10,
- max = math.max,
- min = math.min,
- modf = math.modf,
- pi = math.pi,
- pow = math.pow,
- rad = math.rad,
- random = math.random,
- sin = math.sin,
- sinh = math.sinh,
- sqrt = math.sqrt,
- tan = math.tan,
- tanh = math.tanh,
- },
- table = {
- insert = table.insert,
- maxn = table.maxn,
- remove = table.remove,
- sort = table.sort
- },
- event = event,
+ local vports_copy = {}
+ for k, v in pairs(vports) do vports_copy[k] = v end
+ local rports = get_real_port_states(pos)
+
+ -- Create new library tables on each call to prevent one LuaController
+ -- from breaking a library and messing up other LuaControllers.
+ local env = {
+ pin = merge_port_states(vports, rports),
+ port = vports_copy,
+ event = event,
+ mem = mem,
+ heat = minetest.get_meta(pos):get_int("heat"),
+ heat_max = mesecon.setting("overheat_max", 20),
+ print = safe_print,
+ interrupt = get_interrupt(pos),
+ digiline_send = get_digiline_send(pos),
+ string = {
+ byte = string.byte,
+ char = string.char,
+ format = string.format,
+ gsub = string.gsub,
+ len = string.len,
+ lower = string.lower,
+ upper = string.upper,
+ rep = string.rep,
+ reverse = string.reverse,
+ sub = string.sub,
+ },
+ math = {
+ abs = math.abs,
+ acos = math.acos,
+ asin = math.asin,
+ atan = math.atan,
+ atan2 = math.atan2,
+ ceil = math.ceil,
+ cos = math.cos,
+ cosh = math.cosh,
+ deg = math.deg,
+ exp = math.exp,
+ floor = math.floor,
+ fmod = math.fmod,
+ frexp = math.frexp,
+ huge = math.huge,
+ ldexp = math.ldexp,
+ log = math.log,
+ log10 = math.log10,
+ max = math.max,
+ min = math.min,
+ modf = math.modf,
+ pi = math.pi,
+ pow = math.pow,
+ rad = math.rad,
+ random = math.random,
+ sin = math.sin,
+ sinh = math.sinh,
+ sqrt = math.sqrt,
+ tan = math.tan,
+ tanh = math.tanh,
+ },
+ table = {
+ concat = table.concat,
+ insert = table.insert,
+ maxn = table.maxn,
+ remove = table.remove,
+ sort = table.sort,
+ },
+ os = {
+ clock = os.clock,
+ difftime = os.difftime,
+ time = os.time,
+ },
}
+ env._G = env
+
+ for _, name in pairs(safe_globals) do
+ env[name] = _G[name]
+ end
+
+ return env
end
-local create_sandbox = function (code, env)
- -- Create Sandbox
+
+local function timeout()
+ debug.sethook() -- Clear hook
+ error("Code timed out!")
+end
+
+
+local function code_prohibited(code)
+ -- LuaJIT doesn't increment the instruction counter when running
+ -- loops, so we have to sanitize inputs if we're using LuaJIT.
+ if not jit then
+ return false
+ end
+ local prohibited = {"while", "for", "do", "repeat", "until", "goto"}
+ code = " "..code.." "
+ for _, p in ipairs(prohibited) do
+ if string.find(code, "[^%w_]"..p.."[^%w_]") then
+ return "Prohibited command: "..p
+ end
+ end
+end
+
+
+local function create_sandbox(code, env)
if code:byte(1) == 27 then
- return _, "You Hacker You! Don't use binary code!"
+ return nil, "Binary code prohibited."
end
local f, msg = loadstring(code)
- if not f then return _, msg end
+ if not f then return nil, msg end
setfenv(f, env)
- return f
-end
-local lc_overheat = function (pos, meta)
- if mesecon.do_overheat(pos) then -- if too hot
- local node = minetest.get_node(pos)
- minetest.swap_node(pos, {name = BASENAME.."_burnt", param2 = node.param2})
- minetest.after(0.2, overheat_off, pos) -- wait for pending operations
- return true
+ return function(...)
+ debug.sethook(timeout, "", 10000)
+ local ok, ret = pcall(f, ...)
+ debug.sethook() -- Clear hook
+ if not ok then error(ret) end
+ return ret
end
end
-local load_memory = function(meta)
+
+local function load_memory(meta)
return minetest.deserialize(meta:get_string("lc_memory")) or {}
end
-local save_memory = function(meta, mem)
- meta:set_string("lc_memory", safe_serialize(mem))
-end
-local ports_invalid = function (var)
- if type(var) == "table" then
- return false
- end
- return "The ports you set are invalid"
+local function save_memory(meta, mem)
+ meta:set_string("lc_memory",
+ minetest.serialize(
+ remove_functions(mem)
+ )
+ )
end
-----------------------
--- Parsing function --
-----------------------
-lc_update = function (pos, event)
+local function run(pos, event)
local meta = minetest.get_meta(pos)
- if lc_overheat(pos) then return end
+ if overheat(pos) then return end
- -- load code & mem from memory
+ -- Load code & mem from meta
local mem = load_memory(meta)
local code = meta:get_string("code")
- -- make sure code is ok and create environment
- local prohibited = code_prohibited(code)
- if prohibited then return prohibited end
+ local err = code_prohibited(code)
+ if err then return err end
+
+ -- Create environment
local env = create_environment(pos, mem, event)
- -- create the sandbox and execute code
- local chunk, msg = create_sandbox (code, env)
- if not chunk then return msg end
- local success, msg = pcall(chunk)
+ -- Create the sandbox and execute code
+ local f, msg = create_sandbox(code, env)
+ if not f then return msg end
+ local success, msg = pcall(f)
if not success then return msg end
- if ports_invalid(env.port) then return ports_invalid(env.port) end
+ if type(env.port) ~= "table" then
+ return "Ports set are invalid."
+ end
- save_memory(meta, mem)
+ save_memory(meta, env.mem)
-- Actually set the ports
- action(pos, env.port)
+ set_port_states(pos, env.port)
end
-local reset_meta = function(pos, code, errmsg)
+mesecon.queue:add_function("lc_interrupt", function (pos, luac_id, iid)
+ -- There is no luacontroller anymore / it has been reprogrammed / replaced
+ if (minetest.get_meta(pos):get_int("luac_id") ~= luac_id) then return end
+ run(pos, {type="interrupt", iid = iid})
+end)
+
+local function reset_meta(pos, code, errmsg)
local meta = minetest.get_meta(pos)
meta:set_string("code", code)
code = minetest.formspec_escape(code or "")
@@ -336,172 +410,155 @@ local reset_meta = function(pos, code, errmsg)
"image_button_exit[9.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]"..
"label[0.1,5;"..errmsg.."]")
meta:set_int("heat", 0)
- meta:set_int("luac_id", math.random(1, 1000000))
+ meta:set_int("luac_id", math.random(1, 65535))
end
-local reset = function (pos)
- action(pos, {a=false, b=false, c=false, d=false})
+local function reset(pos)
+ set_port_states(pos, {a=false, b=false, c=false, d=false})
end
--- ______
--- |
--- |
--- | __ ___ _ __ _ _
--- | | | | | |\ | | |_| | | | | |_ |_|
--- |___| |______ |__| | \| | | \ |__| |_ |_ |_ |\
--- |
--- |
---
-----------------------
-- Node Registration --
-----------------------
-local output_rules={}
-local input_rules={}
+local output_rules = {}
+local input_rules = {}
-local nodebox = {
- 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
- }
+local node_box = {
+ 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
}
+}
-local selectionbox = {
- type = "fixed",
- fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
- }
+local selection_box = {
+ type = "fixed",
+ fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
+}
local digiline = {
receptor = {},
effector = {
- action = function (pos, node, channel, msg)
- lc_update (pos, {type = "digiline", channel = channel, msg = msg})
+ action = function(pos, node, channel, msg)
+ run(pos, {type = "digiline", channel = channel, msg = msg})
end
}
}
+local function on_receive_fields(pos, form_name, fields)
+ if not fields.program then
+ return
+ end
+ reset(pos)
+ reset_meta(pos, fields.code)
+ local err = run(pos, {type="program"})
+ if err then
+ print(err)
+ reset_meta(pos, fields.code, err)
+ end
+end
-for a = 0, 1 do -- 0 = off; 1 = on
+for a = 0, 1 do -- 0 = off 1 = on
for b = 0, 1 do
for c = 0, 1 do
for d = 0, 1 do
+ local cid = tostring(d)..tostring(c)..tostring(b)..tostring(a)
+ local node_name = BASENAME..cid
+ local top = "jeija_luacontroller_top.png"
+ if a == 1 then
+ top = top.."^jeija_luacontroller_LED_A.png"
+ end
+ if b == 1 then
+ top = top.."^jeija_luacontroller_LED_B.png"
+ end
+ if c == 1 then
+ top = top.."^jeija_luacontroller_LED_C.png"
+ end
+ if d == 1 then
+ top = top.."^jeija_luacontroller_LED_D.png"
+ end
-local cid = tostring(d)..tostring(c)..tostring(b)..tostring(a)
-local nodename = BASENAME..cid
-local top = "jeija_luacontroller_top.png"
-if a == 1 then
- top = top.."^jeija_luacontroller_LED_A.png"
-end
-if b == 1 then
- top = top.."^jeija_luacontroller_LED_B.png"
-end
-if c == 1 then
- top = top.."^jeija_luacontroller_LED_C.png"
-end
-if d == 1 then
- top = top.."^jeija_luacontroller_LED_D.png"
-end
-
-if a + b + c + d ~= 0 then
- groups = {dig_immediate=2, not_in_creative_inventory=1, overheat = 1}
-else
- groups = {dig_immediate=2, overheat = 1}
-end
+ local groups
+ if a + b + c + d ~= 0 then
+ groups = {dig_immediate=2, not_in_creative_inventory=1, overheat = 1}
+ else
+ groups = {dig_immediate=2, overheat = 1}
+ end
-output_rules[cid] = {}
-input_rules[cid] = {}
-if (a == 1) then table.insert(output_rules[cid], rules.a) end
-if (b == 1) then table.insert(output_rules[cid], rules.b) end
-if (c == 1) then table.insert(output_rules[cid], rules.c) end
-if (d == 1) then table.insert(output_rules[cid], rules.d) end
-
-if (a == 0) then table.insert(input_rules[cid], rules.a) end
-if (b == 0) then table.insert(input_rules[cid], rules.b) end
-if (c == 0) then table.insert(input_rules[cid], rules.c) end
-if (d == 0) then table.insert(input_rules[cid], rules.d) end
-
-local mesecons = {
- effector =
- {
- rules = input_rules[cid],
- action_change = function (pos, _, rulename, newstate)
- lc_update_real_portstates(pos, rulename, newstate)
- lc_update(pos, {type=newstate, pin=rulename})
- end,
- },
- receptor =
- {
- state = mesecon.state.on,
- rules = output_rules[cid]
+ output_rules[cid] = {}
+ input_rules[cid] = {}
+ if a == 1 then table.insert(output_rules[cid], rules.a) end
+ if b == 1 then table.insert(output_rules[cid], rules.b) end
+ if c == 1 then table.insert(output_rules[cid], rules.c) end
+ if d == 1 then table.insert(output_rules[cid], rules.d) end
+
+ if a == 0 then table.insert( input_rules[cid], rules.a) end
+ if b == 0 then table.insert( input_rules[cid], rules.b) end
+ if c == 0 then table.insert( input_rules[cid], rules.c) end
+ if d == 0 then table.insert( input_rules[cid], rules.d) end
+
+ local mesecons = {
+ effector = {
+ rules = input_rules[cid],
+ action_change = function (pos, _, rule_name, new_state)
+ update_real_port_states(pos, rule_name, new_state)
+ run(pos, {type=new_state, pin=rule_name})
+ end,
+ },
+ receptor = {
+ state = mesecon.state.on,
+ rules = output_rules[cid]
+ }
}
-}
-minetest.register_node(nodename, {
- description = "Luacontroller",
- drawtype = "nodebox",
- tiles = {
- top,
- "jeija_microcontroller_bottom.png",
- "jeija_microcontroller_sides.png",
- "jeija_microcontroller_sides.png",
- "jeija_microcontroller_sides.png",
- "jeija_microcontroller_sides.png"
+ minetest.register_node(node_name, {
+ description = "LuaController",
+ drawtype = "nodebox",
+ tiles = {
+ top,
+ "jeija_microcontroller_bottom.png",
+ "jeija_microcontroller_sides.png",
+ "jeija_microcontroller_sides.png",
+ "jeija_microcontroller_sides.png",
+ "jeija_microcontroller_sides.png"
},
-
- inventory_image = top,
- paramtype = "light",
- groups = groups,
- drop = BASENAME.."0000",
- sunlight_propagates = true,
- selection_box = selectionbox,
- node_box = nodebox,
- on_construct = reset_meta,
- on_receive_fields = function(pos, formname, fields)
- if not fields.program then
- return
- end
- reset(pos)
- reset_meta(pos, fields.code)
- local err = lc_update(pos, {type="program"})
- if err then
- print(err)
- reset_meta(pos, fields.code, err)
- end
- end,
- sounds = default.node_sound_stone_defaults(),
- mesecons = mesecons,
- digiline = digiline,
- virtual_portstates = { a = a == 1, -- virtual portstates are
- b = b == 1, -- the ports the the
- c = c == 1, -- controller powers itself
- d = d == 1},-- so those that light up
- after_dig_node = function (pos, node)
- mesecon.receptor_off(pos, output_rules)
- end,
- is_luacontroller = true,
-})
+ inventory_image = top,
+ paramtype = "light",
+ groups = groups,
+ drop = BASENAME.."0000",
+ sunlight_propagates = true,
+ selection_box = selection_box,
+ node_box = node_box,
+ on_construct = reset_meta,
+ on_receive_fields = on_receive_fields,
+ on_timer = handle_timer,
+ sounds = default.node_sound_stone_defaults(),
+ mesecons = mesecons,
+ digiline = digiline,
+ -- Virtual portstates are the ports that
+ -- the node shows as powered up (light up).
+ virtual_portstates = {
+ a = a == 1,
+ b = b == 1,
+ c = c == 1,
+ d = d == 1,
+ },
+ after_dig_node = function (pos, node)
+ mesecon.receptor_off(pos, output_rules)
+ end,
+ is_luacontroller = true,
+ })
end
end
end
end
------------------------------
--- overheated luacontroller --
+-- Overheated LuaController --
------------------------------
-local mesecons_burnt = {
- effector =
- {
- rules = mesecon.rules.flat,
- action_change = function (pos, _, rulename, newstate)
- -- only update portstates when changes are triggered
- lc_update_real_portstates(pos, rulename, newstate)
- end
- }
-}
-
minetest.register_node(BASENAME .. "_burnt", {
drawtype = "nodebox",
tiles = {
@@ -518,23 +575,19 @@ minetest.register_node(BASENAME .. "_burnt", {
drop = BASENAME.."0000",
sunlight_propagates = true,
selection_box = selectionbox,
- node_box = nodebox,
+ node_box = node_box,
on_construct = reset_meta,
- on_receive_fields = function(pos, formname, fields)
- if fields.quit then
- return
- end
- reset(pos)
- reset_meta(pos, fields.code)
- local err = lc_update(pos, {type="program"})
- if err then
- print(err)
- reset_meta(pos, fields.code, err)
- end
- end,
+ on_receive_fields = on_receive_fields,
sounds = default.node_sound_stone_defaults(),
virtual_portstates = {a = false, b = false, c = false, d = false},
- mesecons = mesecons_burnt,
+ mesecons = {
+ effector = {
+ rules = mesecon.rules.flat,
+ action_change = function(pos, _, rule_name, new_state)
+ update_real_port_states(pos, rule_name, new_state)
+ end,
+ },
+ },
})
------------------------