From bd749ec4d41e90fc5b9d0217f09892082ab5e256 Mon Sep 17 00:00:00 2001 From: Jeija Date: Sun, 13 Jan 2013 00:18:25 +0100 Subject: Add luacontroller, a microcontroller that you can code in lua. It still misses some functionality such as a persistent memory and a timer, but that is subject to change. The code runs in a sandbox. Speaking long term this will hopefully replace the old controller. --- mesecons_luacontroller/depends.txt | 1 + mesecons_luacontroller/init.lua | 303 +++++++++++++++++++++ mesecons_textures/textures/jeija_close_window.png | Bin 0 -> 7701 bytes .../textures/jeija_luacontroller_LED_A.png | Bin 0 -> 3541 bytes .../textures/jeija_luacontroller_LED_B.png | Bin 0 -> 3537 bytes .../textures/jeija_luacontroller_LED_C.png | Bin 0 -> 3537 bytes .../textures/jeija_luacontroller_LED_D.png | Bin 0 -> 3537 bytes .../textures/jeija_luacontroller_top.png | Bin 0 -> 11913 bytes 8 files changed, 304 insertions(+) create mode 100644 mesecons_luacontroller/depends.txt create mode 100644 mesecons_luacontroller/init.lua create mode 100644 mesecons_textures/textures/jeija_close_window.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_A.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_B.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_C.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_LED_D.png create mode 100644 mesecons_textures/textures/jeija_luacontroller_top.png diff --git a/mesecons_luacontroller/depends.txt b/mesecons_luacontroller/depends.txt new file mode 100644 index 0000000..acaa924 --- /dev/null +++ b/mesecons_luacontroller/depends.txt @@ -0,0 +1 @@ +mesecons diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua new file mode 100644 index 0000000..e3aa6fd --- /dev/null +++ b/mesecons_luacontroller/init.lua @@ -0,0 +1,303 @@ +-- 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, ports, vports): activates/deactivates the mesecons according to the portstates (helper for action) +-- action(pos, ports): Applies new portstates to a luacontroller at pos +-- 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 +-- +-- The Sandbox +-- The whole code of the controller runs in a sandbox, +-- a very restricted environment. +-- However, as this does not prevent you from using e.g. loops, +-- we need to check for these prohibited commands first. +-- Actually the only way to damage the server is to +-- use too much memory from the sandbox. +-- You can add more functions to the environment +-- (see where local env is defined) +-- Something nice to play is is appending minetest.env to it. + +local BASENAME = "mesecons_luacontroller:luacontroller" + +local rules = {} +rules.a = {x = -1, y = 0, z = 0} +rules.b = {x = 0, y = 0, z = 1} +rules.c = {x = 1, y = 0, z = 0} +rules.d = {x = 0, y = 0, z = -1} + +local get_real_portstates = function(pos) -- determine if ports are powered (by itself or from outside) + ports = { + a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos), + b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos), + c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos), + d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d)) + and mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos), + } + return ports +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 +end + +local action_setports = function (pos, ports, vports) + if vports.a ~= ports.a then + if ports.a then mesecon:receptor_on(pos, {rules.a}) + else mesecon:receptor_off(pos, {rules.a}) end + end + if vports.b ~= ports.b then + if ports.b then mesecon:receptor_on(pos, {rules.b}) + else mesecon:receptor_off(pos, {rules.b}) end + end + if vports.c ~= ports.c then + if ports.c then mesecon:receptor_on(pos, {rules.c}) + else mesecon:receptor_off(pos, {rules.c}) end + end + if vports.d ~= ports.d then + if ports.d then mesecon:receptor_on(pos, {rules.d}) + else mesecon:receptor_off(pos, {rules.d}) end + end +end + +local action = function (pos, ports) + local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates; + local name = BASENAME + ..tonumber(ports.d and 1 or 0) + ..tonumber(ports.c and 1 or 0) + ..tonumber(ports.b and 1 or 0) + ..tonumber(ports.a and 1 or 0) + mesecon:swap_node(pos, name) + + action_setports (pos, ports, vports) +end + +-- Overheat Stuff +local heat = function (meta) -- warm up + h = meta:get_int("heat") + if h ~= nil then + meta:set_int("heat", h + 1) + end +end + +local cool = function (meta) -- cool down after a while + h = meta:get_int("heat") + if h ~= nil then + meta:set_int("heat", h - 1) + end +end + +local overheat = function (meta) -- determine if too hot + h = meta:get_int("heat") + if h == nil then return true end -- if nil then overheat + if h > 30 then + return true + else + return false + end +end + +local overheat_off = function(pos) + rules = mesecon:get_rules("mesecons_microcontroller:microcontroller1111") + mesecon:receptor_off(pos, rules) +end + +local update = function (pos) + local meta = minetest.env:get_meta(pos) + code = meta:get_string("code") + + -- Clean code + local prohibited = {"while", "for", "repeat", "until"} + for _, p in ipairs(prohibited) do + if string.find(code, p) then + return "Prohibited command: "..p + end + end + + -- Gather variables for the environment + local vports = minetest.registered_nodes[minetest.env: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) + + local env = { print = print, + selfpos = pos, + dump = dump, + pin = merge_portstates(vports, rports), + port = vports} + + -- Create Sandbox + if code:byte(1) == 27 then + return "You Hacker You! Don't use binary code!" + end + local f, msg = loadstring(code) + if not f then return msg end + setfenv(f, env) + success, msg = pcall(f) + + -- Overheat protection + heat(meta) + minetest.after(0.5, cool, meta) + if overheat(meta) then + minetest.env:remove_node(pos) + minetest.after(0.2, overheat_off, pos) -- wait for pending operations + minetest.env:add_item(pos, BASENAME.."0000") + return + end + + -- Actually set the ports + if not success then + return msg + else + action(pos, env.port) + end +end + +local reset_meta = function(pos, code, errmsg) + local meta = minetest.env:get_meta(pos) + code = code or ""; + errmsg = errmsg or ""; + errmsg = string.gsub(errmsg, "%[", "(") -- would otherwise + errmsg = string.gsub(errmsg, "%]", ")") -- corrupt formspec + meta:set_string("code", code) + meta:set_string("formspec", "size[10,8]".. + "textarea[0.2,0.4;10.2,5;code;Code:;"..code.."]".. + "button[3.5,7.5;2,0;program;Program]".. + "image_button_exit[9.62,-0.35;0.7,0.7;jeija_close_window.png;exit;]".. + "label[0.1,4.5;"..errmsg.."]") + meta:set_int("heat", 0) +end + +local reset = function (pos) + action(pos, {a=false, b=false, c=false, d=false}) +end + +-- ______ +-- | +-- | | | +-- |___| | __ ___ _ __ _ _ +-- | | | | |\ | | |_| | | | | |_ |_| +-- | |______ |__| | \| | | \ |__| |_ |_ |_ |\ +-- +-- Actually register all the stuff: + +for a = 0, 1 do +for b = 0, 1 do +for c = 0, 1 do +for d = 0, 1 do +local nodename = BASENAME..tostring(d)..tostring(c)..tostring(b)..tostring(a) +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} +else + groups = {dig_immediate=2} +end + +local output_rules={} +if (a == 1) then table.insert(output_rules, rules.a) end +if (b == 1) then table.insert(output_rules, rules.b) end +if (c == 1) then table.insert(output_rules, rules.c) end +if (d == 1) then table.insert(output_rules, rules.d) end + +local input_rules={} +if (a == 0) then table.insert(input_rules, rules.a) end +if (b == 0) then table.insert(input_rules, rules.b) end +if (c == 0) then table.insert(input_rules, rules.c) end +if (d == 0) then table.insert(input_rules, rules.d) end + +local mesecons = {effector = +{ + rules = input_rules, + action_change = function (pos) + update(pos) + end +}} +if nodename ~= BASENAME.."0000" then + mesecons.receptor = { + state = mesecon.state.on, + rules = output_rules + } +end + +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 selectionbox = { + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, + } + +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" + }, + + 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) + reset(pos) + reset_meta(pos, fields.code) + local err = update(pos) + if err then print(err) end + reset_meta(pos, fields.code, err) + end, + mesecons = mesecons, + 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, +}) +end +end +end +end + +minetest.register_craft({ + output = BASENAME.."0000 2", + recipe = { + {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'group:mesecon_conductor_craftable'}, + {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'group:mesecon_conductor_craftable'}, + {'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable', ''}, + } +}) diff --git a/mesecons_textures/textures/jeija_close_window.png b/mesecons_textures/textures/jeija_close_window.png new file mode 100644 index 0000000..eb89179 Binary files /dev/null and b/mesecons_textures/textures/jeija_close_window.png differ diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_A.png b/mesecons_textures/textures/jeija_luacontroller_LED_A.png new file mode 100644 index 0000000..a187e8e Binary files /dev/null and b/mesecons_textures/textures/jeija_luacontroller_LED_A.png differ diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_B.png b/mesecons_textures/textures/jeija_luacontroller_LED_B.png new file mode 100644 index 0000000..738ba96 Binary files /dev/null and b/mesecons_textures/textures/jeija_luacontroller_LED_B.png differ diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_C.png b/mesecons_textures/textures/jeija_luacontroller_LED_C.png new file mode 100644 index 0000000..abe0fe6 Binary files /dev/null and b/mesecons_textures/textures/jeija_luacontroller_LED_C.png differ diff --git a/mesecons_textures/textures/jeija_luacontroller_LED_D.png b/mesecons_textures/textures/jeija_luacontroller_LED_D.png new file mode 100644 index 0000000..cc10170 Binary files /dev/null and b/mesecons_textures/textures/jeija_luacontroller_LED_D.png differ diff --git a/mesecons_textures/textures/jeija_luacontroller_top.png b/mesecons_textures/textures/jeija_luacontroller_top.png new file mode 100644 index 0000000..3128230 Binary files /dev/null and b/mesecons_textures/textures/jeija_luacontroller_top.png differ -- cgit v1.2.3 From e297a02ec290d68fbb386054d5f8a5f8d2c2ba3e Mon Sep 17 00:00:00 2001 From: Jeija Date: Sun, 13 Jan 2013 11:05:04 +0100 Subject: Implement a memory for the controller (accesible via mem.) and cleanup code Based on PilzAdam's code. --- mesecons_luacontroller/init.lua | 94 ++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index e3aa6fd..f24a8ad 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -26,6 +26,11 @@ rules.b = {x = 0, y = 0, z = 1} rules.c = {x = 1, y = 0, z = 0} rules.d = {x = 0, y = 0, z = -1} +------------------ +-- Action stuff -- +------------------ +-- These helpers are required to set the portstates of the luacontroller + local get_real_portstates = function(pos) -- determine if ports are powered (by itself or from outside) ports = { a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a)) @@ -80,7 +85,10 @@ local action = function (pos, ports) action_setports (pos, ports, vports) end --- Overheat Stuff +-------------------- +-- Overheat stuff -- +-------------------- + local heat = function (meta) -- warm up h = meta:get_int("heat") if h ~= nil then @@ -106,14 +114,14 @@ local overheat = function (meta) -- determine if too hot end local overheat_off = function(pos) - rules = mesecon:get_rules("mesecons_microcontroller:microcontroller1111") - mesecon:receptor_off(pos, rules) + mesecon:receptor_off(pos, mesecon.rules.flat) end -local update = function (pos) - local meta = minetest.env:get_meta(pos) - code = meta:get_string("code") +------------------- +-- Parsing stuff -- +------------------- +local code_prohibited = function(code) -- Clean code local prohibited = {"while", "for", "repeat", "until"} for _, p in ipairs(prohibited) do @@ -121,27 +129,36 @@ local update = function (pos) return "Prohibited command: "..p end end +end + +local safeprint = function(param) + print(dump(param)) +end +local create_environment = function(pos, mem) -- Gather variables for the environment local vports = minetest.registered_nodes[minetest.env: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) - local env = { print = print, - selfpos = pos, - dump = dump, - pin = merge_portstates(vports, rports), - port = vports} + return { print = safeprint, + pin = merge_portstates(vports, rports), + port = vports, + mem = mem} +end +local create_sandbox = function (code, env) -- Create Sandbox if code:byte(1) == 27 then - return "You Hacker You! Don't use binary code!" + return _, "You Hacker You! Don't use binary code!" end - local f, msg = loadstring(code) - if not f then return msg end + f, msg = loadstring(code) + if not f then return _, msg end setfenv(f, env) - success, msg = pcall(f) + return f +end +local do_overheat = function (pos, meta) -- Overheat protection heat(meta) minetest.after(0.5, cool, meta) @@ -151,13 +168,40 @@ local update = function (pos) minetest.env:add_item(pos, BASENAME.."0000") return end +end + +local load_memory = function(meta) + return minetest.deserialize(meta:get_string("lc_memory")) or {} +end + +local save_memory = function(meta, mem) + meta:set_string("lc_memory", minetest.serialize(mem)) +end + +---------------------- +-- Parsing function -- +---------------------- + +local update = function (pos) + local meta = minetest.env:get_meta(pos) + + local mem = load_memory(meta) + local code = meta:get_string("code") + + local prohibited = code_prohibited(code) + if prohibited then return prohibited end + local env = create_environment(pos, mem) + + local chunk, msg = create_sandbox (code, env) + if not chunk then return msg end + local success, msg = pcall(f) + if not success then return msg end + + do_overheat(pos, meta) + save_memory(meta, mem) -- Actually set the ports - if not success then - return msg - else - action(pos, env.port) - end + action(pos, env.port) end local reset_meta = function(pos, code, errmsg) @@ -186,7 +230,10 @@ end -- | | | | |\ | | |_| | | | | |_ |_| -- | |______ |__| | \| | | \ |__| |_ |_ |_ |\ -- --- Actually register all the stuff: + +----------------------- +-- Node Registration -- +----------------------- for a = 0, 1 do for b = 0, 1 do @@ -293,6 +340,10 @@ end end end +------------------------ +-- Craft Registration -- +------------------------ + minetest.register_craft({ output = BASENAME.."0000 2", recipe = { @@ -301,3 +352,4 @@ minetest.register_craft({ {'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable', ''}, } }) + -- cgit v1.2.3 From 240fb83e8b55c66ec223fabe5877257648a0f84e Mon Sep 17 00:00:00 2001 From: Jeija Date: Sun, 13 Jan 2013 17:33:16 +0100 Subject: Implement interrupt(time, iid): The whole code is called again after a certain amount of time. Whenever it is called, an event is set. Possible events are: program, interrupt, on and off It also contains additional information (on/off -> event.in; interrupt -> event.iid) iid must be an integer or string value, otherwise the interrupt is not active --- mesecons_luacontroller/init.lua | 172 +++++++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 53 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index f24a8ad..c125ec9 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -3,7 +3,7 @@ -- newport = merge_portstates(state1, state2): just does result = state1 or state2 for every port -- action_setports(pos, ports, vports): activates/deactivates the mesecons according to the portstates (helper for action) -- action(pos, ports): Applies new portstates to a luacontroller at pos --- update(pos): updates the controller at pos by executing the code +-- 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 -- @@ -21,10 +21,10 @@ local BASENAME = "mesecons_luacontroller:luacontroller" local rules = {} -rules.a = {x = -1, y = 0, z = 0} -rules.b = {x = 0, y = 0, z = 1} -rules.c = {x = 1, y = 0, z = 0} -rules.d = {x = 0, y = 0, z = -1} +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"} ------------------ -- Action stuff -- @@ -54,35 +54,58 @@ local merge_portstates = function (ports, vports) return npo end -local action_setports = function (pos, ports, vports) - if vports.a ~= ports.a then - if ports.a then mesecon:receptor_on(pos, {rules.a}) - else mesecon:receptor_off(pos, {rules.a}) end +local action_setports_on = function (pos, ports, vports) + if vports.a ~= ports.a and ports.a then + mesecon:receptor_on(pos, {rules.a}) end - if vports.b ~= ports.b then - if ports.b then mesecon:receptor_on(pos, {rules.b}) - else mesecon:receptor_off(pos, {rules.b}) end + if vports.b ~= ports.b and ports.b then + mesecon:receptor_on(pos, {rules.b}) end - if vports.c ~= ports.c then - if ports.c then mesecon:receptor_on(pos, {rules.c}) - else mesecon:receptor_off(pos, {rules.c}) end + if vports.c ~= ports.c and ports.c then + mesecon:receptor_on(pos, {rules.c}) end - if vports.d ~= ports.d then - if ports.d then mesecon:receptor_on(pos, {rules.d}) - else mesecon:receptor_off(pos, {rules.d}) end + if vports.d ~= ports.d and ports.d then + mesecon:receptor_on(pos, {rules.d}) + end +end + +local action_setports_off = function (pos, ports, vports) + local todo = {} + if vports.a ~= ports.a and not ports.a then + table.insert(todo, mesecon:addPosRule(pos, rules.a)) + end + if vports.b ~= ports.b and not ports.b then + table.insert(todo, mesecon:addPosRule(pos, rules.b)) + end + if vports.c ~= ports.c and not ports.c then + table.insert(todo, mesecon:addPosRule(pos, rules.c)) + end + if vports.d ~= ports.d and not ports.d then + table.insert(todo, mesecon:addPosRule(pos, rules.d)) + end + + for _, t in ipairs(todo) do + local link, rulename = mesecon:rules_link(pos, t) + if link then + mesecon:turnoff(t, rulename) + end end end local action = function (pos, ports) - local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates; - local name = BASENAME + local name = minetest.env:get_node(pos).name + local vports = minetest.registered_nodes[name].virtual_portstates + local newname = BASENAME ..tonumber(ports.d and 1 or 0) ..tonumber(ports.c and 1 or 0) ..tonumber(ports.b and 1 or 0) ..tonumber(ports.a and 1 or 0) - mesecon:swap_node(pos, name) - action_setports (pos, ports, vports) + if name ~= newname and vports then + action_setports_off (pos, ports, vports) + mesecon:swap_node(pos, newname) + action_setports_on (pos, ports, vports) + end end -------------------- @@ -106,7 +129,7 @@ end local overheat = function (meta) -- determine if too hot h = meta:get_int("heat") if h == nil then return true end -- if nil then overheat - if h > 30 then + if h > 10 then return true else return false @@ -135,7 +158,22 @@ local safeprint = function(param) print(dump(param)) end -local create_environment = function(pos, mem) +local interrupt = function(params) + lc_update(params.pos, {type="interrupt", iid = params.iid}) +end + +local getinterrupt = function(pos) + local interrupt = function (time, iid) -- iid = interrupt id + local meta = minetest.env:get_meta(pos) + local interrupts = minetest.deserialize(meta:get_string("lc_interrupts")) or {} + table.insert (interrupts, iid or 0) + meta:set_string("lc_interrupts", minetest.serialize(interrupts)) + minetest.after(time, interrupt, {pos=pos, iid = iid}) + end + return interrupt +end + +local create_environment = function(pos, mem, event) -- Gather variables for the environment local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates vports = {a = vports.a, b = vports.b, c = vports.c, d = vports.d} @@ -144,7 +182,9 @@ local create_environment = function(pos, mem) return { print = safeprint, pin = merge_portstates(vports, rports), port = vports, - mem = mem} + interrupt = getinterrupt(pos), + mem = mem, + event = event} end local create_sandbox = function (code, env) @@ -178,23 +218,40 @@ local save_memory = function(meta, mem) meta:set_string("lc_memory", minetest.serialize(mem)) end +local interrupt_allow = function (meta, event) + if event.type ~= "interrupt" then return true end + + local interrupts = minetest.deserialize(meta:get_string("lc_interrupts")) or {} + for _, i in ipairs(interrupts) do + if i == event.iid then + return true + end + end + + return false +end + ---------------------- -- Parsing function -- ---------------------- -local update = function (pos) +lc_update = function (pos, event) local meta = minetest.env:get_meta(pos) + if not interrupt_allow(meta, event) then return end + -- load code & mem from memory 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 env = create_environment(pos, mem) + 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(f) + local success, msg = pcall(f, port) if not success then return msg end do_overheat(pos, meta) @@ -235,11 +292,15 @@ end -- Node Registration -- ----------------------- +local output_rules={} +local input_rules={} + for a = 0, 1 do for b = 0, 1 do for c = 0, 1 do for d = 0, 1 do -local nodename = BASENAME..tostring(d)..tostring(c)..tostring(b)..tostring(a) +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" @@ -260,31 +321,35 @@ else groups = {dig_immediate=2} end -local output_rules={} -if (a == 1) then table.insert(output_rules, rules.a) end -if (b == 1) then table.insert(output_rules, rules.b) end -if (c == 1) then table.insert(output_rules, rules.c) end -if (d == 1) then table.insert(output_rules, rules.d) end - -local input_rules={} -if (a == 0) then table.insert(input_rules, rules.a) end -if (b == 0) then table.insert(input_rules, rules.b) end -if (c == 0) then table.insert(input_rules, rules.c) end -if (d == 0) then table.insert(input_rules, rules.d) end - -local mesecons = {effector = -{ - rules = input_rules, - action_change = function (pos) - update(pos) - end -}} -if nodename ~= BASENAME.."0000" then - mesecons.receptor = { +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_on = function (pos, _, rulename) + lc_update(pos, {type="on", pin=rulename}) + end, + action_off = function (pos, _, rulename) + lc_update(pos, {type="off", pin=rulename}) + end + }, + receptor = + { state = mesecon.state.on, - rules = output_rules + rules = output_rules[cid] } -end +} local nodebox = { type = "fixed", @@ -322,11 +387,12 @@ minetest.register_node(nodename, { on_receive_fields = function(pos, formname, fields) reset(pos) reset_meta(pos, fields.code) - local err = update(pos) + local err = lc_update(pos, {type="program"}) if err then print(err) end reset_meta(pos, fields.code, err) end, mesecons = mesecons, + is_luacontroller = true, virtual_portstates = { a = a == 1, -- virtual portstates are b = b == 1, -- the ports the the c = c == 1, -- controller powers itself -- cgit v1.2.3 From 0d441444219816bac6dfd3da0d3997c763bc1669 Mon Sep 17 00:00:00 2001 From: Jeija Date: Mon, 14 Jan 2013 17:58:14 +0100 Subject: Bugfixes and improved stability of the luacontroller --- mesecons_luacontroller/init.lua | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index c125ec9..c72dfa7 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -72,23 +72,16 @@ end local action_setports_off = function (pos, ports, vports) local todo = {} if vports.a ~= ports.a and not ports.a then - table.insert(todo, mesecon:addPosRule(pos, rules.a)) + mesecon:receptor_off(pos, {rules.a}) end if vports.b ~= ports.b and not ports.b then - table.insert(todo, mesecon:addPosRule(pos, rules.b)) + mesecon:receptor_off(pos, {rules.b}) end if vports.c ~= ports.c and not ports.c then - table.insert(todo, mesecon:addPosRule(pos, rules.c)) + mesecon:receptor_off(pos, {rules.c}) end if vports.d ~= ports.d and not ports.d then - table.insert(todo, mesecon:addPosRule(pos, rules.d)) - end - - for _, t in ipairs(todo) do - local link, rulename = mesecon:rules_link(pos, t) - if link then - mesecon:turnoff(t, rulename) - end + mesecon:receptor_off(pos, {rules.d}) end end @@ -102,6 +95,7 @@ local action = function (pos, ports) ..tonumber(ports.a and 1 or 0) if name ~= newname and vports then + mesecon:swap_node(pos, "air") action_setports_off (pos, ports, vports) mesecon:swap_node(pos, newname) action_setports_on (pos, ports, vports) @@ -164,6 +158,7 @@ end local getinterrupt = function(pos) local interrupt = function (time, iid) -- iid = interrupt id + if type(time) ~= "number" then return end local meta = minetest.env:get_meta(pos) local interrupts = minetest.deserialize(meta:get_string("lc_interrupts")) or {} table.insert (interrupts, iid or 0) @@ -223,7 +218,7 @@ local interrupt_allow = function (meta, event) local interrupts = minetest.deserialize(meta:get_string("lc_interrupts")) or {} for _, i in ipairs(interrupts) do - if i == event.iid then + if minetest.serialize(i) == minetest.serialize(event.iid) then return true end end @@ -231,6 +226,13 @@ local interrupt_allow = function (meta, event) return false end +local ports_invalid = function (var) + if type(var) == "table" then + return false + end + return "The ports you set are invalid" +end + ---------------------- -- Parsing function -- ---------------------- @@ -251,8 +253,9 @@ lc_update = function (pos, 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(f, port) + local success, msg = pcall(f) if not success then return msg end + if ports_invalid(env.port) then return ports_invalid(env.port) end do_overheat(pos, meta) save_memory(meta, mem) -- cgit v1.2.3 From ec517becabcc2b80583f3ea2f2b4a3ebec5bc751 Mon Sep 17 00:00:00 2001 From: Jeija Date: Sat, 19 Jan 2013 12:03:27 +0100 Subject: Texture the LuaController formspec --- mesecons_luacontroller/init.lua | 7 ++++--- mesecons_textures/textures/jeija_close_window.png | Bin 7701 -> 323 bytes mesecons_textures/textures/jeija_luac_background.png | Bin 0 -> 2016 bytes mesecons_textures/textures/jeija_luac_runbutton.png | Bin 0 -> 4262 bytes 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 mesecons_textures/textures/jeija_luac_background.png create mode 100644 mesecons_textures/textures/jeija_luac_runbutton.png diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index c72dfa7..f95e072 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -272,9 +272,10 @@ local reset_meta = function(pos, code, errmsg) errmsg = string.gsub(errmsg, "%]", ")") -- corrupt formspec meta:set_string("code", code) meta:set_string("formspec", "size[10,8]".. - "textarea[0.2,0.4;10.2,5;code;Code:;"..code.."]".. - "button[3.5,7.5;2,0;program;Program]".. - "image_button_exit[9.62,-0.35;0.7,0.7;jeija_close_window.png;exit;]".. + "background[-0.2,-0.25;10.4,8.75;jeija_luac_background.png]".. + "textarea[0.2,0.6;10.2,5;code;;"..code.."]".. + "image_button[3.75,6;2.5,1;jeija_luac_runbutton.png;program;]".. + "image_button_exit[9.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]".. "label[0.1,4.5;"..errmsg.."]") meta:set_int("heat", 0) end diff --git a/mesecons_textures/textures/jeija_close_window.png b/mesecons_textures/textures/jeija_close_window.png index eb89179..5c27c6c 100644 Binary files a/mesecons_textures/textures/jeija_close_window.png and b/mesecons_textures/textures/jeija_close_window.png differ diff --git a/mesecons_textures/textures/jeija_luac_background.png b/mesecons_textures/textures/jeija_luac_background.png new file mode 100644 index 0000000..40e316c Binary files /dev/null and b/mesecons_textures/textures/jeija_luac_background.png differ diff --git a/mesecons_textures/textures/jeija_luac_runbutton.png b/mesecons_textures/textures/jeija_luac_runbutton.png new file mode 100644 index 0000000..157507f Binary files /dev/null and b/mesecons_textures/textures/jeija_luac_runbutton.png differ -- cgit v1.2.3 From fc384aedbbd94e234be1cefda80ebe5580e4eda8 Mon Sep 17 00:00:00 2001 From: Jeija Date: Sat, 19 Jan 2013 12:04:10 +0100 Subject: Remove unused variable --- mesecons_luacontroller/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index f95e072..b216c79 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -70,7 +70,6 @@ local action_setports_on = function (pos, ports, vports) end local action_setports_off = function (pos, ports, vports) - local todo = {} if vports.a ~= ports.a and not ports.a then mesecon:receptor_off(pos, {rules.a}) end -- cgit v1.2.3 From 62ddebaecbe0ad42488b66d0aee95a834c43af65 Mon Sep 17 00:00:00 2001 From: Jeija Date: Sat, 19 Jan 2013 21:45:39 +0100 Subject: Add support in luacontroller for a not yet released mod called 'digilines' --- mesecons_luacontroller/init.lua | 49 ++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index b216c79..2a633a6 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -167,6 +167,15 @@ local getinterrupt = function(pos) return interrupt end +local getdigiline_send = function (pos) + local digiline_send = function (channel, msg) + if digiline then + digiline:receptor_send(pos, digiline.rules.default, channel, minetest.serialize(msg)) + end + end + return digiline_send +end + local create_environment = function(pos, mem, event) -- Gather variables for the environment local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates @@ -177,6 +186,7 @@ local create_environment = function(pos, mem, event) pin = merge_portstates(vports, rports), port = vports, interrupt = getinterrupt(pos), + digiline_send = getdigiline_send(pos), mem = mem, event = event} end @@ -200,7 +210,6 @@ local do_overheat = function (pos, meta) minetest.env:remove_node(pos) minetest.after(0.2, overheat_off, pos) -- wait for pending operations minetest.env:add_item(pos, BASENAME.."0000") - return end end @@ -298,6 +307,29 @@ end 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 selectionbox = { + 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", iid = {channel = channel, msg = minetest.deserialize(msg)}}) + end + } +} + for a = 0, 1 do for b = 0, 1 do for c = 0, 1 do @@ -354,20 +386,6 @@ local mesecons = { } } -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 selectionbox = { - type = "fixed", - fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, - } - minetest.register_node(nodename, { description = "Luacontroller", drawtype = "nodebox", @@ -395,6 +413,7 @@ minetest.register_node(nodename, { reset_meta(pos, fields.code, err) end, mesecons = mesecons, + digiline = digiline, is_luacontroller = true, virtual_portstates = { a = a == 1, -- virtual portstates are b = b == 1, -- the ports the the -- cgit v1.2.3 From ef087f2bb63125e041e9ca24d77eb1b987a1b5cc Mon Sep 17 00:00:00 2001 From: Jeija Date: Sat, 19 Jan 2013 22:18:28 +0100 Subject: Fix Bug: Wrong usage of action_on/action_off instead of action_change --- mesecons/init.lua | 2 +- mesecons/internal.lua | 10 +++++----- mesecons_luacontroller/init.lua | 11 ++++------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/mesecons/init.lua b/mesecons/init.lua index 50ed4ca..7f6fe5d 100644 --- a/mesecons/init.lua +++ b/mesecons/init.lua @@ -98,7 +98,7 @@ function mesecon:receptor_off(pos, rules) if not mesecon:connected_to_receptor(np) then mesecon:turnoff(np, rulename) else - mesecon:changesignal(np, minetest.env:get_node(np), rulename) + mesecon:changesignal(np, minetest.env:get_node(np), rulename, mesecon.state.off) end end end diff --git a/mesecons/internal.lua b/mesecons/internal.lua index 2d84787..5e243cf 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -24,7 +24,7 @@ -- SIGNALS -- mesecon:activate(pos, node) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on) -- mesecon:deactivate(pos, node) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off) --- mesecon:changesignal(pos, node) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change) +-- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change) -- RULES -- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name @@ -193,10 +193,10 @@ function mesecon:deactivate(pos, node, rulename) end end -function mesecon:changesignal(pos, node, rulename) +function mesecon:changesignal(pos, node, rulename, newstate) local effector = mesecon:get_effector(node.name) if effector and effector.action_change then - effector.action_change (pos, node, rulename) + effector.action_change (pos, node, rulename, newstate) end end @@ -299,7 +299,7 @@ function mesecon:turnon(pos, rulename) end end elseif mesecon:is_effector(node.name) then - mesecon:changesignal(pos, node, rulename) + mesecon:changesignal(pos, node, rulename, mesecon.state.on) if mesecon:is_effector_off(node.name) then mesecon:activate(pos, node, rulename) end @@ -322,7 +322,7 @@ function mesecon:turnoff(pos, rulename) end end elseif mesecon:is_effector(node.name) then - mesecon:changesignal(pos, node, rulename) + mesecon:changesignal(pos, node, rulename, mesecon.state.off) if mesecon:is_effector_on(node.name) and not mesecon:is_powered(pos) then mesecon:deactivate(pos, node, rulename) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 2a633a6..44c38ff 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -170,7 +170,7 @@ end local getdigiline_send = function (pos) local digiline_send = function (channel, msg) if digiline then - digiline:receptor_send(pos, digiline.rules.default, channel, minetest.serialize(msg)) + digiline:receptor_send(pos, digiline.rules.default, channel, msg) end end return digiline_send @@ -325,7 +325,7 @@ local digiline = { receptor = {}, effector = { action = function (pos, node, channel, msg) - lc_update (pos, {type = "digiline", iid = {channel = channel, msg = minetest.deserialize(msg)}}) + lc_update (pos, {type = "digiline", iid = {channel = channel, msg = msg}}) end } } @@ -372,12 +372,9 @@ local mesecons = { effector = { rules = input_rules[cid], - action_on = function (pos, _, rulename) - lc_update(pos, {type="on", pin=rulename}) + action_change = function (pos, _, rulename, newstate) + lc_update(pos, {type=newstate, pin=rulename}) end, - action_off = function (pos, _, rulename) - lc_update(pos, {type="off", pin=rulename}) - end }, receptor = { -- cgit v1.2.3 From 18da94006af36bf200fc88f0dbd9aaa2270982db Mon Sep 17 00:00:00 2001 From: Jeija Date: Sun, 20 Jan 2013 17:48:43 +0100 Subject: Lots of bugfixes concerning the luacontroller - Bug when using NOT-Gates - Moved error label a little downwards - On digiline event, msg and channel are now in event.*, not in event.iid.* --- mesecons_luacontroller/init.lua | 88 ++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 44c38ff..1967888 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -54,50 +54,46 @@ local merge_portstates = function (ports, vports) return npo end -local action_setports_on = function (pos, ports, vports) - if vports.a ~= ports.a and ports.a then - mesecon:receptor_on(pos, {rules.a}) - end - if vports.b ~= ports.b and ports.b then - mesecon:receptor_on(pos, {rules.b}) - end - if vports.c ~= ports.c and ports.c then - mesecon:receptor_on(pos, {rules.c}) - end - if vports.d ~= ports.d and ports.d then - mesecon:receptor_on(pos, {rules.d}) - end -end - -local action_setports_off = function (pos, ports, vports) - if vports.a ~= ports.a and not ports.a then - mesecon:receptor_off(pos, {rules.a}) - end - if vports.b ~= ports.b and not ports.b then - mesecon:receptor_off(pos, {rules.b}) - end - if vports.c ~= ports.c and not ports.c then - mesecon:receptor_off(pos, {rules.c}) - end - if vports.d ~= ports.d and not ports.d then - mesecon:receptor_off(pos, {rules.d}) - end +local generate_name = function (ports, overwrite) + local overwrite = overwrite or {} + local d = overwrite.d or (ports.d and 1 or 0) + local c = overwrite.d or (ports.c and 1 or 0) + local b = overwrite.d or (ports.b and 1 or 0) + local a = overwrite.d or (ports.a and 1 or 0) + return BASENAME..d..c..b..a end local action = function (pos, ports) local name = minetest.env:get_node(pos).name local vports = minetest.registered_nodes[name].virtual_portstates - local newname = BASENAME - ..tonumber(ports.d and 1 or 0) - ..tonumber(ports.c and 1 or 0) - ..tonumber(ports.b and 1 or 0) - ..tonumber(ports.a and 1 or 0) + local newname = generate_name(ports) if name ~= newname and vports then - mesecon:swap_node(pos, "air") - action_setports_off (pos, ports, vports) - mesecon:swap_node(pos, newname) - action_setports_on (pos, ports, vports) + local rules_on = {} + local rules_off = {} + local ignore = {} + + if ports.a then table.insert(rules_on, rules.a) + else table.insert(rules_off, rules.a) end + if ports.b then table.insert(rules_on, rules.b) + else table.insert(rules_off, rules.b) end + if ports.c then table.insert(rules_on, rules.c) + else table.insert(rules_off, rules.c) end + if ports.d then table.insert(rules_on, rules.d) + else table.insert(rules_off, rules.d) end + + if ports.a ~= vports.a then ignore.a = 2 end + if ports.b ~= vports.b then ignore.b = 2 end + if ports.c ~= vports.c then ignore.c = 2 end + if ports.d ~= vports.d then ignore.d = 2 end + + mesecon:swap_node(pos, generate_name(ports, ignore)) + mesecon:receptor_off(pos, rules_off) + if minetest.env:get_node(pos).name ~= generate_name(ports, ignore) then return end -- not interrupted by another event + mesecon:receptor_on (pos, rules_on ) + if minetest.registered_nodes[minetest.env:get_node(pos).name].is_luacontroller then --didnt overheat + mesecon:swap_node(pos, newname) + end end end @@ -122,7 +118,7 @@ end local overheat = function (meta) -- determine if too hot h = meta:get_int("heat") if h == nil then return true end -- if nil then overheat - if h > 10 then + if h > 20 then return true else return false @@ -210,6 +206,7 @@ local do_overheat = function (pos, meta) minetest.env:remove_node(pos) minetest.after(0.2, overheat_off, pos) -- wait for pending operations minetest.env:add_item(pos, BASENAME.."0000") + return true end end @@ -248,6 +245,7 @@ end lc_update = function (pos, event) local meta = minetest.env:get_meta(pos) if not interrupt_allow(meta, event) then return end + if do_overheat(pos, meta) then return end -- load code & mem from memory local mem = load_memory(meta) @@ -265,7 +263,6 @@ lc_update = function (pos, event) if not success then return msg end if ports_invalid(env.port) then return ports_invalid(env.port) end - do_overheat(pos, meta) save_memory(meta, mem) -- Actually set the ports @@ -284,7 +281,7 @@ local reset_meta = function(pos, code, errmsg) "textarea[0.2,0.6;10.2,5;code;;"..code.."]".. "image_button[3.75,6;2.5,1;jeija_luac_runbutton.png;program;]".. "image_button_exit[9.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]".. - "label[0.1,4.5;"..errmsg.."]") + "label[0.1,5;"..errmsg.."]") meta:set_int("heat", 0) end @@ -325,15 +322,16 @@ local digiline = { receptor = {}, effector = { action = function (pos, node, channel, msg) - lc_update (pos, {type = "digiline", iid = {channel = channel, msg = msg}}) + lc_update (pos, {type = "digiline", channel = channel, msg = msg}) end } } -for a = 0, 1 do -for b = 0, 1 do -for c = 0, 1 do -for d = 0, 1 do +for a = 0, 2 do -- 0 = off; 1 = on; 2 = ignore +for b = 0, 2 do +for c = 0, 2 do +for d = 0, 2 do + local cid = tostring(d)..tostring(c)..tostring(b)..tostring(a) local nodename = BASENAME..cid local top = "jeija_luacontroller_top.png" -- cgit v1.2.3 From 2b30360da23cedecdd45f2a8060d87a9e3038ac8 Mon Sep 17 00:00:00 2001 From: Jeija Date: Tue, 22 Jan 2013 18:26:27 +0100 Subject: Bugfix for the luacontroller that occured when two events occur at the same time (output connected to input). The behaviour of the controller can now be described this way: The luacontroller sets port A, then B, then C, then D; if it is interrupted by another event during that time it stops and let the second event do the job. --- mesecons_luacontroller/init.lua | 50 ++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 1967888..76e08bd 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -63,7 +63,21 @@ local generate_name = function (ports, overwrite) return BASENAME..d..c..b..a end -local action = function (pos, ports) +local setport = function (pos, rule, ignore, state, ports) + local ignorename = generate_name(ports, ignore) + mesecon:swap_node(pos, ignorename) + if state then + mesecon:receptor_on(pos, {rule}) + else + mesecon:receptor_off(pos, {rule}) + end + if minetest.env:get_node(pos).name ~= ignorename then + return true -- overridden by second process + end + return false -- success +end + +local action = function (pos, ports, forcereset) local name = minetest.env:get_node(pos).name local vports = minetest.registered_nodes[name].virtual_portstates local newname = generate_name(ports) @@ -73,27 +87,17 @@ local action = function (pos, ports) local rules_off = {} local ignore = {} - if ports.a then table.insert(rules_on, rules.a) - else table.insert(rules_off, rules.a) end - if ports.b then table.insert(rules_on, rules.b) - else table.insert(rules_off, rules.b) end - if ports.c then table.insert(rules_on, rules.c) - else table.insert(rules_off, rules.c) end - if ports.d then table.insert(rules_on, rules.d) - else table.insert(rules_off, rules.d) end - - if ports.a ~= vports.a then ignore.a = 2 end - if ports.b ~= vports.b then ignore.b = 2 end - if ports.c ~= vports.c then ignore.c = 2 end - if ports.d ~= vports.d then ignore.d = 2 end - - mesecon:swap_node(pos, generate_name(ports, ignore)) - mesecon:receptor_off(pos, rules_off) - if minetest.env:get_node(pos).name ~= generate_name(ports, ignore) then return end -- not interrupted by another event - mesecon:receptor_on (pos, rules_on ) - if minetest.registered_nodes[minetest.env:get_node(pos).name].is_luacontroller then --didnt overheat - mesecon:swap_node(pos, newname) - end + local interrupted + if ports.a ~= vports.a then interrupted = setport(pos, rules.a, {a = 2}, ports.a, ports) end + if interrupted and not forcereset then return end + if ports.b ~= vports.b then interrupted = setport(pos, rules.b, {b = 2}, ports.b, ports) end + if interrupted and not forcereset then return end + if ports.c ~= vports.c then interrupted = setport(pos, rules.c, {c = 2}, ports.c, ports) end + if interrupted and not forcereset then return end + if ports.d ~= vports.d then interrupted = setport(pos, rules.d, {d = 2}, ports.d, ports) end + if interrupted and not forcereset then return end + + mesecon:swap_node(pos, newname) end end @@ -286,7 +290,7 @@ local reset_meta = function(pos, code, errmsg) end local reset = function (pos) - action(pos, {a=false, b=false, c=false, d=false}) + action(pos, {a=false, b=false, c=false, d=false}, true) end -- ______ -- cgit v1.2.3 From 59cd72191b89e15dfd901dde487c6eb13252c3ba Mon Sep 17 00:00:00 2001 From: Jeija Date: Tue, 22 Jan 2013 21:15:49 +0100 Subject: Add tostring, tonumber, string to luacontroller, prohibit 'function' --- mesecons_luacontroller/init.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 76e08bd..344e0d3 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -139,7 +139,7 @@ end local code_prohibited = function(code) -- Clean code - local prohibited = {"while", "for", "repeat", "until"} + local prohibited = {"while", "for", "repeat", "until", "function"} for _, p in ipairs(prohibited) do if string.find(code, p) then return "Prohibited command: "..p @@ -188,6 +188,9 @@ local create_environment = function(pos, mem, event) interrupt = getinterrupt(pos), digiline_send = getdigiline_send(pos), mem = mem, + tostring = tostring, + tonumber = tonumber, + string = string, event = event} end -- cgit v1.2.3 From 591e2d7cde9eda88ca85b71066dd9ed7f75f9a12 Mon Sep 17 00:00:00 2001 From: Jeija Date: Sun, 10 Feb 2013 23:08:59 +0100 Subject: LuaController: Queue setting the ports (wait for pending operations) --- mesecons_luacontroller/init.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 344e0d3..91551a1 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -101,6 +101,10 @@ local action = function (pos, ports, forcereset) end end +local delayedaction = function (params) + action(params.pos, params.ports) +end + -------------------- -- Overheat stuff -- -------------------- @@ -273,7 +277,7 @@ lc_update = function (pos, event) save_memory(meta, mem) -- Actually set the ports - action(pos, env.port) + minetest.after(0, delayedaction, {pos = pos, ports = env.port}) end local reset_meta = function(pos, code, errmsg) -- cgit v1.2.3 From eeed4f148d95dd418ecee54fc6dfb22ab47f5f1b Mon Sep 17 00:00:00 2001 From: Jeija Date: Tue, 12 Feb 2013 10:25:24 +0100 Subject: Fix odd behaviour when using interrupts in the luacontroller --- mesecons_luacontroller/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 91551a1..5141f8a 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -162,9 +162,10 @@ end local getinterrupt = function(pos) local interrupt = function (time, iid) -- iid = interrupt id if type(time) ~= "number" then return end + local iid = iid or math.random() local meta = minetest.env:get_meta(pos) local interrupts = minetest.deserialize(meta:get_string("lc_interrupts")) or {} - table.insert (interrupts, iid or 0) + table.insert (interrupts, iid) meta:set_string("lc_interrupts", minetest.serialize(interrupts)) minetest.after(time, interrupt, {pos=pos, iid = iid}) end @@ -297,6 +298,7 @@ local reset_meta = function(pos, code, errmsg) end local reset = function (pos) + minetest.env:get_meta(pos):set_string("lc_interrupts", "") action(pos, {a=false, b=false, c=false, d=false}, true) end -- cgit v1.2.3 From 1c4ab938ad6d1a45dc30d0f276c75b248f9796cf Mon Sep 17 00:00:00 2001 From: Jeija Date: Tue, 12 Feb 2013 10:58:29 +0100 Subject: Fix a dumb bug that conflicted with different things in the luacontroller --- mesecons_luacontroller/init.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 5141f8a..d0c98ad 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -57,9 +57,9 @@ end local generate_name = function (ports, overwrite) local overwrite = overwrite or {} local d = overwrite.d or (ports.d and 1 or 0) - local c = overwrite.d or (ports.c and 1 or 0) - local b = overwrite.d or (ports.b and 1 or 0) - local a = overwrite.d or (ports.a and 1 or 0) + local c = overwrite.c or (ports.c and 1 or 0) + local b = overwrite.b or (ports.b and 1 or 0) + local a = overwrite.a or (ports.a and 1 or 0) return BASENAME..d..c..b..a end -- cgit v1.2.3