forked from Mirrorlandia_minetest/mesecons
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
This commit is contained in:
parent
e297a02ec2
commit
240fb83e8b
@ -3,7 +3,7 @@
|
|||||||
-- newport = merge_portstates(state1, state2): just does result = state1 or state2 for every port
|
-- 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_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
|
-- 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_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
|
-- reset (pos): performs a hardware reset, turns off all ports
|
||||||
--
|
--
|
||||||
@ -21,10 +21,10 @@
|
|||||||
local BASENAME = "mesecons_luacontroller:luacontroller"
|
local BASENAME = "mesecons_luacontroller:luacontroller"
|
||||||
|
|
||||||
local rules = {}
|
local rules = {}
|
||||||
rules.a = {x = -1, y = 0, z = 0}
|
rules.a = {x = -1, y = 0, z = 0, name="A"}
|
||||||
rules.b = {x = 0, y = 0, z = 1}
|
rules.b = {x = 0, y = 0, z = 1, name="B"}
|
||||||
rules.c = {x = 1, y = 0, z = 0}
|
rules.c = {x = 1, y = 0, z = 0, name="C"}
|
||||||
rules.d = {x = 0, y = 0, z = -1}
|
rules.d = {x = 0, y = 0, z = -1, name="D"}
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
-- Action stuff --
|
-- Action stuff --
|
||||||
@ -54,35 +54,58 @@ local merge_portstates = function (ports, vports)
|
|||||||
return npo
|
return npo
|
||||||
end
|
end
|
||||||
|
|
||||||
local action_setports = function (pos, ports, vports)
|
local action_setports_on = function (pos, ports, vports)
|
||||||
if vports.a ~= ports.a then
|
if vports.a ~= ports.a and ports.a then
|
||||||
if ports.a then mesecon:receptor_on(pos, {rules.a})
|
mesecon:receptor_on(pos, {rules.a})
|
||||||
else mesecon:receptor_off(pos, {rules.a}) end
|
|
||||||
end
|
end
|
||||||
if vports.b ~= ports.b then
|
if vports.b ~= ports.b and ports.b then
|
||||||
if ports.b then mesecon:receptor_on(pos, {rules.b})
|
mesecon:receptor_on(pos, {rules.b})
|
||||||
else mesecon:receptor_off(pos, {rules.b}) end
|
|
||||||
end
|
end
|
||||||
if vports.c ~= ports.c then
|
if vports.c ~= ports.c and ports.c then
|
||||||
if ports.c then mesecon:receptor_on(pos, {rules.c})
|
mesecon:receptor_on(pos, {rules.c})
|
||||||
else mesecon:receptor_off(pos, {rules.c}) end
|
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
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
local action = function (pos, ports)
|
local action = function (pos, ports)
|
||||||
local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates;
|
local name = minetest.env:get_node(pos).name
|
||||||
local name = BASENAME
|
local vports = minetest.registered_nodes[name].virtual_portstates
|
||||||
|
local newname = BASENAME
|
||||||
..tonumber(ports.d and 1 or 0)
|
..tonumber(ports.d and 1 or 0)
|
||||||
..tonumber(ports.c and 1 or 0)
|
..tonumber(ports.c and 1 or 0)
|
||||||
..tonumber(ports.b and 1 or 0)
|
..tonumber(ports.b and 1 or 0)
|
||||||
..tonumber(ports.a 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
|
end
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
@ -106,7 +129,7 @@ end
|
|||||||
local overheat = function (meta) -- determine if too hot
|
local overheat = function (meta) -- determine if too hot
|
||||||
h = meta:get_int("heat")
|
h = meta:get_int("heat")
|
||||||
if h == nil then return true end -- if nil then overheat
|
if h == nil then return true end -- if nil then overheat
|
||||||
if h > 30 then
|
if h > 10 then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
@ -135,7 +158,22 @@ local safeprint = function(param)
|
|||||||
print(dump(param))
|
print(dump(param))
|
||||||
end
|
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
|
-- Gather variables for the environment
|
||||||
local vports = minetest.registered_nodes[minetest.env:get_node(pos).name].virtual_portstates
|
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}
|
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,
|
return { print = safeprint,
|
||||||
pin = merge_portstates(vports, rports),
|
pin = merge_portstates(vports, rports),
|
||||||
port = vports,
|
port = vports,
|
||||||
mem = mem}
|
interrupt = getinterrupt(pos),
|
||||||
|
mem = mem,
|
||||||
|
event = event}
|
||||||
end
|
end
|
||||||
|
|
||||||
local create_sandbox = function (code, env)
|
local create_sandbox = function (code, env)
|
||||||
@ -178,23 +218,40 @@ local save_memory = function(meta, mem)
|
|||||||
meta:set_string("lc_memory", minetest.serialize(mem))
|
meta:set_string("lc_memory", minetest.serialize(mem))
|
||||||
end
|
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 --
|
-- Parsing function --
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
local update = function (pos)
|
lc_update = function (pos, event)
|
||||||
local meta = minetest.env:get_meta(pos)
|
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 mem = load_memory(meta)
|
||||||
local code = meta:get_string("code")
|
local code = meta:get_string("code")
|
||||||
|
|
||||||
|
-- make sure code is ok and create environment
|
||||||
local prohibited = code_prohibited(code)
|
local prohibited = code_prohibited(code)
|
||||||
if prohibited then return prohibited end
|
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)
|
local chunk, msg = create_sandbox (code, env)
|
||||||
if not chunk then return msg end
|
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
|
if not success then return msg end
|
||||||
|
|
||||||
do_overheat(pos, meta)
|
do_overheat(pos, meta)
|
||||||
@ -235,11 +292,15 @@ end
|
|||||||
-- Node Registration --
|
-- Node Registration --
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
local output_rules={}
|
||||||
|
local input_rules={}
|
||||||
|
|
||||||
for a = 0, 1 do
|
for a = 0, 1 do
|
||||||
for b = 0, 1 do
|
for b = 0, 1 do
|
||||||
for c = 0, 1 do
|
for c = 0, 1 do
|
||||||
for d = 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"
|
local top = "jeija_luacontroller_top.png"
|
||||||
if a == 1 then
|
if a == 1 then
|
||||||
top = top.."^jeija_luacontroller_LED_A.png"
|
top = top.."^jeija_luacontroller_LED_A.png"
|
||||||
@ -260,31 +321,35 @@ else
|
|||||||
groups = {dig_immediate=2}
|
groups = {dig_immediate=2}
|
||||||
end
|
end
|
||||||
|
|
||||||
local output_rules={}
|
output_rules[cid] = {}
|
||||||
if (a == 1) then table.insert(output_rules, rules.a) end
|
input_rules[cid] = {}
|
||||||
if (b == 1) then table.insert(output_rules, rules.b) end
|
if (a == 1) then table.insert(output_rules[cid], rules.a) end
|
||||||
if (c == 1) then table.insert(output_rules, rules.c) end
|
if (b == 1) then table.insert(output_rules[cid], rules.b) end
|
||||||
if (d == 1) then table.insert(output_rules, rules.d) 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
|
||||||
|
|
||||||
local input_rules={}
|
if (a == 0) then table.insert(input_rules[cid], rules.a) end
|
||||||
if (a == 0) then table.insert(input_rules, rules.a) end
|
if (b == 0) then table.insert(input_rules[cid], rules.b) end
|
||||||
if (b == 0) then table.insert(input_rules, rules.b) end
|
if (c == 0) then table.insert(input_rules[cid], rules.c) end
|
||||||
if (c == 0) then table.insert(input_rules, rules.c) end
|
if (d == 0) then table.insert(input_rules[cid], rules.d) end
|
||||||
if (d == 0) then table.insert(input_rules, rules.d) end
|
|
||||||
|
|
||||||
local mesecons = {effector =
|
local mesecons = {
|
||||||
{
|
effector =
|
||||||
rules = input_rules,
|
{
|
||||||
action_change = function (pos)
|
rules = input_rules[cid],
|
||||||
update(pos)
|
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
|
end
|
||||||
}}
|
},
|
||||||
if nodename ~= BASENAME.."0000" then
|
receptor =
|
||||||
mesecons.receptor = {
|
{
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
rules = output_rules
|
rules = output_rules[cid]
|
||||||
}
|
}
|
||||||
end
|
}
|
||||||
|
|
||||||
local nodebox = {
|
local nodebox = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -322,11 +387,12 @@ minetest.register_node(nodename, {
|
|||||||
on_receive_fields = function(pos, formname, fields)
|
on_receive_fields = function(pos, formname, fields)
|
||||||
reset(pos)
|
reset(pos)
|
||||||
reset_meta(pos, fields.code)
|
reset_meta(pos, fields.code)
|
||||||
local err = update(pos)
|
local err = lc_update(pos, {type="program"})
|
||||||
if err then print(err) end
|
if err then print(err) end
|
||||||
reset_meta(pos, fields.code, err)
|
reset_meta(pos, fields.code, err)
|
||||||
end,
|
end,
|
||||||
mesecons = mesecons,
|
mesecons = mesecons,
|
||||||
|
is_luacontroller = true,
|
||||||
virtual_portstates = { a = a == 1, -- virtual portstates are
|
virtual_portstates = { a = a == 1, -- virtual portstates are
|
||||||
b = b == 1, -- the ports the the
|
b = b == 1, -- the ports the the
|
||||||
c = c == 1, -- controller powers itself
|
c = c == 1, -- controller powers itself
|
||||||
|
Loading…
Reference in New Issue
Block a user