diff options
Diffstat (limited to 'mesecons_luacontroller')
-rw-r--r-- | mesecons_luacontroller/init.lua | 131 |
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}, }) |