2014-08-07 04:54:17 +02:00
|
|
|
-- ______
|
|
|
|
-- |
|
|
|
|
-- |
|
|
|
|
-- | __ ___ _ __ _ _
|
|
|
|
-- | | | | | |\ | | |_| | | | | |_ |_|
|
|
|
|
-- |___| |______ |__| | \| | | \ |__| |_ |_ |_ |\
|
|
|
|
-- |
|
|
|
|
-- |
|
|
|
|
--
|
|
|
|
|
2013-01-13 00:18:25 +01:00
|
|
|
-- Reference
|
2014-08-07 04:54:17 +02:00
|
|
|
-- 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
|
2017-02-15 19:52:29 +01:00
|
|
|
-- set_port_states(pos, ports): Applies new port states to a Luacontroller at pos
|
2018-01-22 12:26:21 +01:00
|
|
|
-- run_inner(pos, code, event): runs code on the controller at pos and event
|
|
|
|
-- reset_formspec(pos, code, errmsg): installs new code and prints error messages, without resetting LCID
|
|
|
|
-- reset_meta(pos, code, errmsg): performs a software-reset, installs new code and prints error message
|
|
|
|
-- run(pos, event): a wrapper for run_inner which gets code & handles errors via reset_meta
|
2014-08-07 04:54:17 +02:00
|
|
|
-- resetn(pos): performs a hardware reset, turns off all ports
|
2013-01-13 00:18:25 +01:00
|
|
|
--
|
|
|
|
-- The Sandbox
|
|
|
|
-- The whole code of the controller runs in a sandbox,
|
|
|
|
-- a very restricted environment.
|
|
|
|
-- 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"
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
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"},
|
|
|
|
}
|
|
|
|
|
2013-01-13 00:18:25 +01:00
|
|
|
|
2013-01-13 11:05:04 +01:00
|
|
|
------------------
|
|
|
|
-- Action stuff --
|
|
|
|
------------------
|
2014-08-07 04:54:17 +02:00
|
|
|
-- These helpers are required to set the port states of the luacontroller
|
2013-01-13 11:05:04 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
local function update_real_port_states(pos, rule_name, new_state)
|
2014-01-10 16:38:02 +01:00
|
|
|
local meta = minetest.get_meta(pos)
|
2014-08-07 04:54:17 +02:00
|
|
|
if rule_name == nil then
|
2014-01-10 16:38:02 +01:00
|
|
|
meta:set_int("real_portstates", 1)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local n = meta:get_int("real_portstates") - 1
|
|
|
|
local L = {}
|
|
|
|
for i = 1, 4 do
|
2014-08-07 04:54:17 +02:00
|
|
|
L[i] = n % 2
|
|
|
|
n = math.floor(n / 2)
|
2014-01-10 16:38:02 +01:00
|
|
|
end
|
2014-08-07 04:54:17 +02:00
|
|
|
-- (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]
|
2014-01-10 16:38:02 +01:00
|
|
|
L[port] = (newstate == "on") and 1 or 0
|
|
|
|
end
|
|
|
|
else
|
2014-08-07 04:54:17 +02:00
|
|
|
local port = pos_to_side[rule_name.x + (2 * rule_name.z) + 3]
|
|
|
|
L[port] = (new_state == "on") and 1 or 0
|
2014-01-10 16:38:02 +01:00
|
|
|
end
|
2014-08-07 04:54:17 +02:00
|
|
|
meta:set_int("real_portstates",
|
|
|
|
1 +
|
|
|
|
1 * L[1] +
|
|
|
|
2 * L[2] +
|
|
|
|
4 * L[3] +
|
|
|
|
8 * L[4])
|
2014-01-10 16:38:02 +01:00
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
|
|
|
|
local port_names = {"a", "b", "c", "d"}
|
|
|
|
|
|
|
|
local function get_real_port_states(pos)
|
|
|
|
-- Determine if ports are powered (by itself or from outside)
|
2014-01-10 16:38:02 +01:00
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local L = {}
|
|
|
|
local n = meta:get_int("real_portstates") - 1
|
2014-08-07 04:54:17 +02:00
|
|
|
for _, name in ipairs(port_names) do
|
|
|
|
L[name] = ((n % 2) == 1)
|
|
|
|
n = math.floor(n / 2)
|
2014-01-10 16:38:02 +01:00
|
|
|
end
|
|
|
|
return L
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
local function generate_name(ports)
|
2013-04-01 22:24:01 +02:00
|
|
|
local d = ports.d and 1 or 0
|
|
|
|
local c = ports.c and 1 or 0
|
|
|
|
local b = ports.b and 1 or 0
|
|
|
|
local a = ports.a and 1 or 0
|
2013-01-20 17:48:43 +01:00
|
|
|
return BASENAME..d..c..b..a
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
|
|
|
|
local function set_port(pos, rule, state)
|
2013-01-22 18:26:27 +01:00
|
|
|
if state then
|
2014-11-22 15:42:22 +01:00
|
|
|
mesecon.receptor_on(pos, {rule})
|
2013-01-22 18:26:27 +01:00
|
|
|
else
|
2014-11-22 15:42:22 +01:00
|
|
|
mesecon.receptor_off(pos, {rule})
|
2013-01-22 18:26:27 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
|
|
|
|
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)
|
2013-12-01 02:20:01 +01:00
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
local name = node.name
|
2014-08-07 04:54:17 +02:00
|
|
|
clean_port_states(ports)
|
2013-01-13 17:33:16 +01:00
|
|
|
local vports = minetest.registered_nodes[name].virtual_portstates
|
2014-08-07 04:54:17 +02:00
|
|
|
local new_name = generate_name(ports)
|
2013-01-22 18:26:27 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
if name ~= new_name and vports then
|
2014-11-29 10:56:09 +01:00
|
|
|
-- Problem:
|
|
|
|
-- We need to place the new node first so that when turning
|
|
|
|
-- off some port, it won't stay on because the rules indicate
|
|
|
|
-- there is an onstate output port there.
|
|
|
|
-- When turning the output off then, it will however cause feedback
|
|
|
|
-- so that the luacontroller will receive an "off" event by turning
|
|
|
|
-- its output off.
|
|
|
|
-- Solution / Workaround:
|
|
|
|
-- Remember which output was turned off and ignore next "off" event.
|
|
|
|
local meta = minetest.get_meta(pos)
|
2018-01-22 12:26:21 +01:00
|
|
|
local ign = minetest.deserialize(meta:get_string("ignore_offevents"), true) or {}
|
2014-11-29 10:56:09 +01:00
|
|
|
if ports.a and not vports.a and not mesecon.is_powered(pos, rules.a) then ign.A = true end
|
|
|
|
if ports.b and not vports.b and not mesecon.is_powered(pos, rules.b) then ign.B = true end
|
|
|
|
if ports.c and not vports.c and not mesecon.is_powered(pos, rules.c) then ign.C = true end
|
|
|
|
if ports.d and not vports.d and not mesecon.is_powered(pos, rules.d) then ign.D = true end
|
|
|
|
meta:set_string("ignore_offevents", minetest.serialize(ign))
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
minetest.swap_node(pos, {name = new_name, param2 = node.param2})
|
2013-01-13 00:18:25 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
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
|
2013-04-01 22:24:01 +02:00
|
|
|
end
|
2013-02-10 23:08:59 +01:00
|
|
|
end
|
|
|
|
|
2013-01-13 11:05:04 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
-----------------
|
|
|
|
-- Overheating --
|
|
|
|
-----------------
|
2015-10-18 11:28:35 +02:00
|
|
|
local function burn_controller(pos)
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
node.name = BASENAME.."_burnt"
|
|
|
|
minetest.swap_node(pos, node)
|
|
|
|
minetest.get_meta(pos):set_string("lc_memory", "");
|
|
|
|
-- Wait for pending operations
|
|
|
|
minetest.after(0.2, mesecon.receptor_off, pos, mesecon.rules.flat)
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
local function overheat(pos, meta)
|
|
|
|
if mesecon.do_overheat(pos) then -- If too hot
|
2015-10-18 11:28:35 +02:00
|
|
|
burn_controller(pos)
|
2014-08-07 04:54:17 +02:00
|
|
|
return true
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
2013-01-13 11:05:04 +01:00
|
|
|
end
|
|
|
|
|
2014-11-29 10:56:09 +01:00
|
|
|
------------------------
|
|
|
|
-- Ignored off events --
|
|
|
|
------------------------
|
|
|
|
|
|
|
|
local function ignore_event(event, meta)
|
|
|
|
if event.type ~= "off" then return false end
|
2018-01-22 12:26:21 +01:00
|
|
|
local ignore_offevents = minetest.deserialize(meta:get_string("ignore_offevents"), true) or {}
|
2014-11-29 10:56:09 +01:00
|
|
|
if ignore_offevents[event.pin.name] then
|
|
|
|
ignore_offevents[event.pin.name] = nil
|
|
|
|
meta:set_string("ignore_offevents", minetest.serialize(ignore_offevents))
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
2013-01-13 00:18:25 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
-------------------------
|
|
|
|
-- Parsing and running --
|
|
|
|
-------------------------
|
|
|
|
|
2019-01-01 21:49:09 +01:00
|
|
|
local function save_memory(pos, meta, memstring)
|
2015-10-18 11:28:35 +02:00
|
|
|
local memsize_max = mesecon.setting("luacontroller_memsize", 100000)
|
|
|
|
|
|
|
|
if (#memstring <= memsize_max) then
|
|
|
|
meta:set_string("lc_memory", memstring)
|
2018-09-17 21:47:19 +02:00
|
|
|
meta:mark_as_private("lc_memory")
|
2015-10-18 11:28:35 +02:00
|
|
|
else
|
|
|
|
print("Error: Luacontroller memory overflow. "..memsize_max.." bytes available, "
|
|
|
|
..#memstring.." required. Controller overheats.")
|
|
|
|
burn_controller(pos)
|
|
|
|
end
|
2013-01-14 17:58:14 +01:00
|
|
|
end
|
|
|
|
|
2018-01-22 12:26:21 +01:00
|
|
|
-- Returns success (boolean), errmsg (string)
|
|
|
|
-- run (as opposed to run_inner) is responsible for setting up meta according to this output
|
|
|
|
local function run_inner(pos, code, event)
|
2013-12-01 04:13:00 +01:00
|
|
|
local meta = minetest.get_meta(pos)
|
2018-01-22 12:26:21 +01:00
|
|
|
-- Note: These return success, presumably to avoid changing LC ID.
|
|
|
|
if overheat(pos) then return true, "" end
|
|
|
|
if ignore_event(event, meta) then return true, "" end
|
2013-01-13 11:05:04 +01:00
|
|
|
|
2019-01-01 21:49:09 +01:00
|
|
|
local vports = minetest.registered_nodes[minetest.get_node(pos).name].virtual_portstates
|
|
|
|
local vports_copy = {}
|
|
|
|
for k, v in pairs(vports) do vports_copy[k] = v end
|
|
|
|
local rports = get_real_port_states(pos)
|
|
|
|
local pin = merge_port_states(vports, rports)
|
|
|
|
local port = vports_copy
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
-- Load code & mem from meta
|
2019-01-01 21:49:09 +01:00
|
|
|
local mem = meta:get_string("lc_memory")
|
2013-01-13 11:05:04 +01:00
|
|
|
local code = meta:get_string("code")
|
2019-01-01 21:49:09 +01:00
|
|
|
local success, port, mem = mesecons_sandbox.run(pin, port, mem, code)
|
|
|
|
if not success then return false, port end
|
2013-01-13 11:05:04 +01:00
|
|
|
|
2019-01-01 21:49:09 +01:00
|
|
|
set_port_states(pos, port)
|
|
|
|
save_memory(pos, meta, mem)
|
2013-01-13 00:18:25 +01:00
|
|
|
|
2019-01-01 21:49:09 +01:00
|
|
|
return true
|
2018-01-22 12:26:21 +01:00
|
|
|
end
|
2014-11-25 17:20:05 +01:00
|
|
|
|
2018-01-22 12:26:21 +01:00
|
|
|
local function reset_formspec(meta, code, errmsg)
|
2013-03-15 22:46:59 +01:00
|
|
|
meta:set_string("code", code)
|
2018-09-17 21:55:53 +02:00
|
|
|
meta:mark_as_private("code")
|
2013-12-01 04:13:00 +01:00
|
|
|
code = minetest.formspec_escape(code or "")
|
2017-05-08 16:33:05 +02:00
|
|
|
errmsg = minetest.formspec_escape(tostring(errmsg or ""))
|
2018-12-09 13:50:02 +01:00
|
|
|
meta:set_string("formspec", "size[12,10]"
|
|
|
|
.."background[-0.2,-0.25;12.4,10.75;jeija_luac_background.png]"
|
|
|
|
.."label[0.1,8.3;"..errmsg.."]"
|
|
|
|
.."textarea[0.2,0.2;12.2,9.5;code;;"..code.."]"
|
|
|
|
.."image_button[4.75,8.75;2.5,1;jeija_luac_runbutton.png;program;]"
|
|
|
|
.."image_button_exit[11.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]"
|
|
|
|
)
|
2018-01-22 12:26:21 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
local function reset_meta(pos, code, errmsg)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
reset_formspec(meta, code, errmsg)
|
2014-08-07 04:54:17 +02:00
|
|
|
meta:set_int("luac_id", math.random(1, 65535))
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
|
2018-01-22 12:26:21 +01:00
|
|
|
-- Wraps run_inner with LC-reset-on-error
|
|
|
|
local function run(pos, event)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local code = meta:get_string("code")
|
|
|
|
local ok, errmsg = run_inner(pos, code, event)
|
|
|
|
if not ok then
|
|
|
|
reset_meta(pos, code, errmsg)
|
|
|
|
else
|
|
|
|
reset_formspec(meta, code, errmsg)
|
|
|
|
end
|
|
|
|
return ok, errmsg
|
|
|
|
end
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
local function reset(pos)
|
|
|
|
set_port_states(pos, {a=false, b=false, c=false, d=false})
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
|
2018-12-29 21:48:32 +01:00
|
|
|
local function node_timer(pos)
|
|
|
|
if minetest.registered_nodes[minetest.get_node(pos).name].is_burnt then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
run(pos, {type="interrupt"})
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2018-01-22 12:26:21 +01:00
|
|
|
-----------------------
|
|
|
|
-- A.Queue callbacks --
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
mesecon.queue:add_function("lc_interrupt", function (pos, luac_id, iid)
|
|
|
|
-- There is no luacontroller anymore / it has been reprogrammed / replaced / burnt
|
|
|
|
if (minetest.get_meta(pos):get_int("luac_id") ~= luac_id) then return end
|
|
|
|
if (minetest.registered_nodes[minetest.get_node(pos).name].is_burnt) then return end
|
|
|
|
run(pos, {type="interrupt", iid = iid})
|
|
|
|
end)
|
|
|
|
|
|
|
|
mesecon.queue:add_function("lc_digiline_relay", function (pos, channel, luac_id, msg)
|
|
|
|
if not digiline then return end
|
|
|
|
-- This check is only really necessary because in case of server crash, old actions can be thrown into the future
|
|
|
|
if (minetest.get_meta(pos):get_int("luac_id") ~= luac_id) then return end
|
|
|
|
if (minetest.registered_nodes[minetest.get_node(pos).name].is_burnt) then return end
|
|
|
|
-- The actual work
|
|
|
|
digiline:receptor_send(pos, digiline.rules.default, channel, msg)
|
|
|
|
end)
|
2013-01-13 11:05:04 +01:00
|
|
|
|
|
|
|
-----------------------
|
|
|
|
-- Node Registration --
|
|
|
|
-----------------------
|
2013-01-13 00:18:25 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
local output_rules = {}
|
|
|
|
local input_rules = {}
|
2013-01-13 17:33:16 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
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
|
2013-01-19 21:45:39 +01:00
|
|
|
}
|
2014-08-07 04:54:17 +02:00
|
|
|
}
|
2013-01-19 21:45:39 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
local selection_box = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
|
|
|
|
}
|
2013-01-19 21:45:39 +01:00
|
|
|
|
|
|
|
local digiline = {
|
|
|
|
receptor = {},
|
|
|
|
effector = {
|
2014-08-07 04:54:17 +02:00
|
|
|
action = function(pos, node, channel, msg)
|
2018-01-13 20:27:01 +01:00
|
|
|
msg = clean_and_weigh_digiline_message(msg)
|
2014-08-07 04:54:17 +02:00
|
|
|
run(pos, {type = "digiline", channel = channel, msg = msg})
|
2013-01-19 21:45:39 +01:00
|
|
|
end
|
|
|
|
}
|
|
|
|
}
|
2017-10-18 21:54:28 +02:00
|
|
|
|
|
|
|
local function get_program(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
return meta:get_string("code")
|
|
|
|
end
|
|
|
|
|
|
|
|
local function set_program(pos, code)
|
|
|
|
reset(pos)
|
|
|
|
reset_meta(pos, code)
|
2018-01-22 12:26:21 +01:00
|
|
|
return run(pos, {type="program"})
|
2017-10-18 21:54:28 +02:00
|
|
|
end
|
|
|
|
|
2016-05-16 19:55:58 +02:00
|
|
|
local function on_receive_fields(pos, form_name, fields, sender)
|
2014-08-07 04:54:17 +02:00
|
|
|
if not fields.program then
|
|
|
|
return
|
|
|
|
end
|
2016-05-16 19:55:58 +02:00
|
|
|
local name = sender:get_player_name()
|
|
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
|
|
minetest.record_protection_violation(pos, name)
|
|
|
|
return
|
|
|
|
end
|
2017-10-18 21:54:28 +02:00
|
|
|
local ok, err = set_program(pos, fields.code)
|
|
|
|
if not ok then
|
|
|
|
-- it's not an error from the server perspective
|
2018-07-18 21:49:34 +02:00
|
|
|
minetest.log("action", "Lua controller programming error: " .. tostring(err))
|
2014-08-07 04:54:17 +02:00
|
|
|
end
|
|
|
|
end
|
2013-01-19 21:45:39 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
for a = 0, 1 do -- 0 = off 1 = on
|
2013-04-01 22:24:01 +02:00
|
|
|
for b = 0, 1 do
|
|
|
|
for c = 0, 1 do
|
|
|
|
for d = 0, 1 do
|
2014-08-07 04:54:17 +02:00
|
|
|
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
|
2013-01-20 17:48:43 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
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
|
2013-01-13 00:18:25 +01:00
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
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)
|
2014-11-29 10:56:09 +01:00
|
|
|
run(pos, {type=new_state, pin=rule_name})
|
2014-08-07 04:54:17 +02:00
|
|
|
end,
|
|
|
|
},
|
|
|
|
receptor = {
|
|
|
|
state = mesecon.state.on,
|
|
|
|
rules = output_rules[cid]
|
2017-10-18 21:54:28 +02:00
|
|
|
},
|
|
|
|
luacontroller = {
|
|
|
|
get_program = get_program,
|
|
|
|
set_program = set_program,
|
|
|
|
},
|
2013-01-13 00:18:25 +01:00
|
|
|
}
|
|
|
|
|
2014-08-07 04:54:17 +02:00
|
|
|
minetest.register_node(node_name, {
|
2017-02-15 19:52:29 +01:00
|
|
|
description = "Luacontroller",
|
2014-08-07 04:54:17 +02:00
|
|
|
drawtype = "nodebox",
|
|
|
|
tiles = {
|
|
|
|
top,
|
|
|
|
"jeija_microcontroller_bottom.png",
|
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
"jeija_microcontroller_sides.png"
|
2013-01-13 00:18:25 +01:00
|
|
|
},
|
2014-08-07 04:54:17 +02:00
|
|
|
inventory_image = top,
|
|
|
|
paramtype = "light",
|
2017-10-31 22:50:39 +01:00
|
|
|
is_ground_content = false,
|
2014-08-07 04:54:17 +02:00
|
|
|
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,
|
|
|
|
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)
|
2017-04-14 21:14:17 +02:00
|
|
|
mesecon.do_cooldown(pos)
|
2014-11-22 23:04:34 +01:00
|
|
|
mesecon.receptor_off(pos, output_rules)
|
2014-08-07 04:54:17 +02:00
|
|
|
end,
|
|
|
|
is_luacontroller = true,
|
2018-12-29 21:48:32 +01:00
|
|
|
on_timer = node_timer,
|
2017-10-07 00:44:49 +02:00
|
|
|
on_blast = mesecon.on_blastnode,
|
2014-08-07 04:54:17 +02:00
|
|
|
})
|
2013-01-13 00:18:25 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-04-20 21:44:58 +02:00
|
|
|
------------------------------
|
2017-02-15 19:52:29 +01:00
|
|
|
-- Overheated Luacontroller --
|
2014-04-20 21:44:58 +02:00
|
|
|
------------------------------
|
|
|
|
|
2013-05-16 03:36:16 +02:00
|
|
|
minetest.register_node(BASENAME .. "_burnt", {
|
|
|
|
drawtype = "nodebox",
|
|
|
|
tiles = {
|
|
|
|
"jeija_luacontroller_burnt_top.png",
|
|
|
|
"jeija_microcontroller_bottom.png",
|
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
"jeija_microcontroller_sides.png"
|
|
|
|
},
|
|
|
|
inventory_image = "jeija_luacontroller_burnt_top.png",
|
2015-10-18 11:28:35 +02:00
|
|
|
is_burnt = true,
|
2013-05-16 03:36:16 +02:00
|
|
|
paramtype = "light",
|
2017-10-31 22:50:39 +01:00
|
|
|
is_ground_content = false,
|
2013-05-16 03:36:16 +02:00
|
|
|
groups = {dig_immediate=2, not_in_creative_inventory=1},
|
|
|
|
drop = BASENAME.."0000",
|
|
|
|
sunlight_propagates = true,
|
2014-12-20 10:11:12 +01:00
|
|
|
selection_box = selection_box,
|
2014-11-22 23:14:45 +01:00
|
|
|
node_box = node_box,
|
2013-05-16 03:36:16 +02:00
|
|
|
on_construct = reset_meta,
|
2014-08-07 04:54:17 +02:00
|
|
|
on_receive_fields = on_receive_fields,
|
2013-05-16 03:36:16 +02:00
|
|
|
sounds = default.node_sound_stone_defaults(),
|
|
|
|
virtual_portstates = {a = false, b = false, c = false, d = false},
|
2014-08-07 04:54:17 +02:00
|
|
|
mesecons = {
|
|
|
|
effector = {
|
|
|
|
rules = mesecon.rules.flat,
|
|
|
|
action_change = function(pos, _, rule_name, new_state)
|
2014-11-22 23:14:45 +01:00
|
|
|
update_real_port_states(pos, rule_name, new_state)
|
2014-08-07 04:54:17 +02:00
|
|
|
end,
|
|
|
|
},
|
|
|
|
},
|
2017-10-07 00:44:49 +02:00
|
|
|
on_blast = mesecon.on_blastnode,
|
2013-05-16 03:36:16 +02:00
|
|
|
})
|
|
|
|
|
2013-01-13 11:05:04 +01:00
|
|
|
------------------------
|
|
|
|
-- Craft Registration --
|
|
|
|
------------------------
|
|
|
|
|
2013-01-13 00:18:25 +01:00
|
|
|
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', ''},
|
|
|
|
}
|
|
|
|
})
|
2013-01-13 11:05:04 +01:00
|
|
|
|