summaryrefslogtreecommitdiff
path: root/mesecons_luacontroller/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'mesecons_luacontroller/init.lua')
-rw-r--r--mesecons_luacontroller/init.lua131
1 files changed, 69 insertions, 62 deletions
diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua
index acbf023..de3a972 100644
--- a/mesecons_luacontroller/init.lua
+++ b/mesecons_luacontroller/init.lua
@@ -31,18 +31,46 @@ rules.d = {x = 0, y = 0, z = -1, name="D"}
------------------
-- These helpers are required to set the portstates of the luacontroller
+function lc_update_real_portstates(pos, rulename, newstate)
+ local meta = minetest.get_meta(pos)
+ if rulename == nil then
+ meta:set_int("real_portstates", 1)
+ return
+ end
+ local n = meta:get_int("real_portstates") - 1
+ if n < 0 then
+ legacy_update_ports(pos)
+ n = meta:get_int("real_portstates") - 1
+ end
+ local L = {}
+ for i = 1, 4 do
+ 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]
+ 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
+ end
+ meta:set_int("real_portstates", 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)
- ports = {
- a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a), mesecon:invertRule(rules.a))
- and mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos),
- b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b), mesecon:invertRule(rules.b))
- and mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos),
- c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c), mesecon:invertRule(rules.c))
- and mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos),
- d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d), mesecon:invertRule(rules.d))
- and mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos),
- }
- return ports
+ local meta = minetest.get_meta(pos)
+ local L = {}
+ local n = meta:get_int("real_portstates") - 1
+ if n < 0 then
+ return legacy_update_ports(pos)
+ end
+ for _, index in ipairs({"a", "b", "c", "d"}) do
+ L[index] = ((n%2) == 1)
+ n = math.floor(n/2)
+ end
+ return L
end
local merge_portstates = function (ports, vports)
@@ -164,40 +192,29 @@ local safe_serialize = function(value)
return minetest.serialize(deep_copy(value))
end
-local interrupt = function(params)
- lc_update(params.pos, {type="interrupt", iid = params.iid})
-end
+mesecon.queue:add_function("lc_interrupt", function (pos, iid, luac_id)
+ -- 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
if type(time) ~= "number" then return end
- local iid = iid or math.random()
- local meta = minetest.get_meta(pos)
- local interrupts = minetest.deserialize(meta:get_string("lc_interrupts")) or {}
- local found = false
- local search = safe_serialize(iid)
- for _, i in ipairs(interrupts) do
- if safe_serialize(i) == search then
- found = true
- break
- end
- end
- if not found then
- table.insert(interrupts, iid)
- meta:set_string("lc_interrupts", safe_serialize(interrupts))
- end
- minetest.after(time, interrupt, {pos=pos, iid = iid})
+ luac_id = minetest.get_meta(pos):get_int("luac_id")
+ mesecon.queue:add_action(pos, "lc_interrupt", {iid, luac_id}, time, iid, 1)
end
return interrupt
end
-local getdigiline_send = function (pos)
- local digiline_send = function (channel, msg)
- if digiline then
+local getdigiline_send = function(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)
- end
+ end)
end
- return digiline_send
end
local create_environment = function(pos, mem, event)
@@ -224,6 +241,7 @@ local create_environment = function(pos, mem, event)
gsub = string.gsub,
len = string.len,
lower = string.lower,
+ upper = string.upper,
match = string.match,
rep = string.rep,
reverse = string.reverse,
@@ -288,7 +306,6 @@ local do_overheat = function (pos, meta)
if overheat(meta) then
local node = minetest.get_node(pos)
minetest.swap_node(pos, {name = BASENAME.."_burnt", param2 = node.param2})
- minetest.get_meta(pos):set_string("lc_interrupts", "")
minetest.after(0.2, overheat_off, pos) -- wait for pending operations
return true
end
@@ -302,20 +319,6 @@ local save_memory = function(meta, mem)
meta:set_string("lc_memory", safe_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 {}
- local search = safe_serialize(event.iid)
- for _, i in ipairs(interrupts) do
- if safe_serialize(i) == search then
- return true
- end
- end
-
- return false
-end
-
local ports_invalid = function (var)
if type(var) == "table" then
return false
@@ -329,7 +332,6 @@ end
lc_update = function (pos, event)
local meta = minetest.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
@@ -338,7 +340,7 @@ lc_update = function (pos, event)
-- make sure code is ok and create environment
local prohibited = code_prohibited(code)
- if prohibited then return prohibited end
+ if prohibited then return prohibited end
local env = create_environment(pos, mem, event)
-- create the sandbox and execute code
@@ -351,7 +353,7 @@ lc_update = function (pos, event)
save_memory(meta, mem)
-- Actually set the ports
- minetest.after(0, action, pos, env.port)
+ action(pos, env.port)
end
local reset_meta = function(pos, code, errmsg)
@@ -366,11 +368,11 @@ 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))
end
local reset = function (pos)
- minetest.get_meta(pos):set_string("lc_interrupts", "")
- action(pos, {a=false, b=false, c=false, d=false}, true)
+ action(pos, {a=false, b=false, c=false, d=false})
end
-- ______
@@ -457,6 +459,7 @@ local mesecons = {
{
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,
},
@@ -488,19 +491,21 @@ minetest.register_node(nodename, {
node_box = nodebox,
on_construct = reset_meta,
on_receive_fields = function(pos, formname, fields)
- if fields.quit then
+ 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) end
- reset_meta(pos, fields.code, err)
+ if err then
+ print(err)
+ reset_meta(pos, fields.code, err)
+ end
end,
+ on_timer = handle_timer,
sounds = default.node_sound_stone_defaults(),
mesecons = mesecons,
digiline = digiline,
- is_luacontroller = true,
virtual_portstates = { a = a == 1, -- virtual portstates are
b = b == 1, -- the ports the the
c = c == 1, -- controller powers itself
@@ -508,6 +513,7 @@ minetest.register_node(nodename, {
after_dig_node = function (pos, node)
mesecon:receptor_off(pos, output_rules)
end,
+ is_luacontroller = true,
})
end
end
@@ -540,11 +546,12 @@ minetest.register_node(BASENAME .. "_burnt", {
reset(pos)
reset_meta(pos, fields.code)
local err = lc_update(pos, {type="program"})
- if err then print(err) end
- reset_meta(pos, fields.code, err)
+ if err then
+ print(err)
+ reset_meta(pos, fields.code, err)
+ end
end,
sounds = default.node_sound_stone_defaults(),
- is_luacontroller = true,
virtual_portstates = {a = false, b = false, c = false, d = false},
})