diff --git a/mesecons/legacy.lua b/mesecons/legacy.lua
index c4334cf85e97d579aed2bbd72116bf3d1566228b..119fa248737e3f66739bc903f75a26969181bf33 100644
--- a/mesecons/legacy.lua
+++ b/mesecons/legacy.lua
@@ -1,18 +1,13 @@
-minetest.swap_node = minetest.swap_node or function(pos, node)
-	local data = minetest.get_meta(pos):to_table()
-	minetest.add_node(pos, node)
-	minetest.get_meta(pos):from_table(data)
-end
-
-local rules = {}
-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"}
+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"},
+}
 
-function legacy_update_ports(pos)
+function mesecon.legacy_update_ports(pos)
 	local meta = minetest.get_meta(pos)
-	L = {
+	local 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),
@@ -26,7 +21,12 @@ function legacy_update_ports(pos)
 			mesecon:invertRule(rules.d)) and
 			mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos),
 	}
-	local n = (L.a and 1 or 0) + (L.b and 2 or 0) + (L.c and 4 or 0) + (L.d and 8 or 0) + 1
+	local n =
+		(ports.a and 1 or 0) +
+		(ports.b and 2 or 0) +
+		(ports.c and 4 or 0) +
+		(ports.d and 8 or 0) + 1
 	meta:set_int("real_portstates", n)
-	return L
+	return ports
 end
+
diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua
index f4869b516c901f51558b67bfc24248dbd8439bfe..f50db1ad23eeb818493081e1df9c878e25b33747 100644
--- a/mesecons_luacontroller/init.lua
+++ b/mesecons_luacontroller/init.lua
@@ -1,11 +1,21 @@
+--        ______
+--       |
+--       |
+--       |        __       ___  _   __         _  _
+-- |   | |       |  | |\ |  |  |_| |  | |  |  |_ |_|
+-- |___| |______ |__| | \|  |  | \ |__| |_ |_ |_ |\
+-- |
+-- |
+--
+
 -- 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, rule, state): activates/deactivates the mesecons according to the portstates (helper for action)
--- action(pos, ports): Applies new portstates to a luacontroller at pos
--- 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
+-- 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
+-- set_port_states(pos, ports): Applies new port states to a LuaController at pos
+-- run(pos): runs the code in the controller at pos
+-- reset_meta(pos, code, errmsg): performs a software-reset, installs new code and prints error messages
+-- resetn(pos): performs a hardware reset, turns off all ports
 --
 -- The Sandbox
 -- The whole code of the controller runs in a sandbox,
@@ -20,70 +30,85 @@
 
 local BASENAME = "mesecons_luacontroller:luacontroller"
 
-local rules = {}
-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"}
+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"},
+}
+
 
 ------------------
 -- Action stuff --
 ------------------
--- These helpers are required to set the portstates of the luacontroller
+-- These helpers are required to set the port states of the luacontroller
 
-function lc_update_real_portstates(pos, rulename, newstate)
+local function update_real_port_states(pos, rule_name, new_state)
 	local meta = minetest.get_meta(pos)
-	if rulename == nil then
+	if rule_name == 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)
+		mesecon.legacy_update_ports(pos)
 		n = meta:get_int("real_portstates") - 1
 	end
+	-- Create list of bytes in n
 	local L = {}
 	for i = 1, 4 do
-		L[i] = n%2
-		n = math.floor(n/2)
+		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]
+	--                   (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]
 			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
+		local port = pos_to_side[rule_name.x + (2 * rule_name.z) + 3]
+		L[port] = (new_state == "on") and 1 or 0
 	end
-	meta:set_int("real_portstates", 1 + L[1] + 2*L[2] + 4*L[3] + 8*L[4])
+	meta:set_int("real_portstates",
+		1 +
+		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)
+
+local port_names = {"a", "b", "c", "d"}
+
+local function get_real_port_states(pos)
+	-- Determine if ports are powered (by itself or from outside)
 	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)
+		return mesecon.legacy_update_ports(pos)
 	end
-	for _, index in ipairs({"a", "b", "c", "d"}) do
-		L[index] = ((n%2) == 1)
-		n = math.floor(n/2)
+	for _, name in ipairs(port_names) do
+		L[name] = ((n % 2) == 1)
+		n = math.floor(n / 2)
 	end
 	return L
 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
+
+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,
+	}
 end
 
-local generate_name = function (ports)
-	local overwrite = overwrite or {}
+
+local function generate_name(ports)
 	local d = ports.d and 1 or 0
 	local c = ports.c and 1 or 0
 	local b = ports.b and 1 or 0
@@ -91,7 +116,8 @@ local generate_name = function (ports)
 	return BASENAME..d..c..b..a
 end
 
-local setport = function (pos, rule, state)
+
+local function set_port(pos, rule, state)
 	if state then
 		mesecon:receptor_on(pos, {rule})
 	else
@@ -99,93 +125,114 @@ local setport = function (pos, rule, state)
 	end
 end
 
-local action = function (pos, ports)
+
+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)
 	local node = minetest.get_node(pos)
 	local name = node.name
+	clean_port_states(ports)
 	local vports = minetest.registered_nodes[name].virtual_portstates
-	local newname = generate_name(ports)
+	local new_name = generate_name(ports)
 
-	if name ~= newname and vports then
-		local rules_on  = {}
-		local rules_off = {}
+	if name ~= new_name and vports then
+		minetest.swap_node(pos, {name = new_name, param2 = node.param2})
 
-		minetest.swap_node(pos, {name = newname, param2 = node.param2})
-
-		if ports.a ~= vports.a then setport(pos, rules.a, ports.a) end
-		if ports.b ~= vports.b then setport(pos, rules.b, ports.b) end
-		if ports.c ~= vports.c then setport(pos, rules.c, ports.c) end
-		if ports.d ~= vports.d then setport(pos, rules.d, ports.d) end
+		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
 	end
 end
 
---------------------
--- Overheat stuff --
---------------------
 
-local overheat_off = function(pos)
+-----------------
+-- Overheating --
+-----------------
+
+local function overheat_off(pos)
 	mesecon:receptor_off(pos, mesecon.rules.flat)
 end
 
--------------------
--- Parsing stuff --
--------------------
 
-local code_prohibited = function(code)
-	-- Clean code
-	local prohibited = {"while", "for", "repeat", "until", "function", "goto"}
-	for _, p in ipairs(prohibited) do
-		if string.find(code, p) then
-			return "Prohibited command: "..p
-		end
+local function overheat(pos, meta)
+	if mesecon.do_overheat(pos) then -- If too hot
+		local node = minetest.get_node(pos)
+		node.name = BASENAME.."_burnt"
+		minetest.swap_node(pos, node)
+		-- Wait for pending operations
+		minetest.after(0.2, overheat_off, pos)
+		return true
 	end
 end
 
-local safe_print = function(param)
-	print(dump(param))
-end
 
-deep_copy = function(original, visited) --deep copy that removes functions
-	visited = visited or {}
-	if visited[original] ~= nil then --already visited this node
-		return visited[original]
+-------------------------
+-- Parsing and running --
+-------------------------
+
+-- Limit printing to prevent flooding
+local print_count = 0
+
+local function safe_print(param)
+	local to_print = dump(param, "")
+	print_count = print_count + 1 + (#to_print / 64)
+	for c in to_print:gmatch("\n") do
+		print_count = print_count + 1
 	end
-	if type(original) == 'table' then --nested table
-		local copy = {}
-		visited[original] = copy
-		for key, value in next, original, nil do
-			copy[deep_copy(key, visited)] = deep_copy(value, visited)
-		end
-		setmetatable(copy, deep_copy(getmetatable(original), visited))
-		return copy
-	elseif type(original) == 'function' then --ignore functions
-		return nil
-	else --by-value type
-		return original
+	if print_count > 8 then
+		error("Too much printing!")
 	end
+	print(to_print)
 end
 
-local safe_serialize = function(value)
-	return minetest.serialize(deep_copy(value))
+minetest.register_globalstep(function(dtime)
+	print_count = print_count - dtime
+end)
+
+
+local function remove_functions(x)
+	local tp = type(x)
+	if tp == "table" then
+		for key, value in pairs(x) do
+			local key_t, val_t = type(key), type(value)
+			if key_t == "function" or val_t == "function" then
+				x[key] = nil
+			else
+				if key_t == "table" then
+					remove_functions(key)
+				end
+				if val_t == "table" then
+					remove_functions(value)
+				end
+			end
+		end
+	elseif tp == "function" then
+		return nil
+	end
+	return x
 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
+local function get_interrupt(pos)
+	-- iid = interrupt id
+	local function interrupt(time, iid)
 		if type(time) ~= "number" then return end
-		luac_id = minetest.get_meta(pos):get_int("luac_id")
-		mesecon.queue:add_action(pos, "lc_interrupt", {iid, luac_id}, time, iid, 1)
+		local luac_id = minetest.get_meta(pos):get_int("luac_id")
+		mesecon.queue:add_action(pos, "LuaController interrupt", {iid, luac_id}, time, iid, 1)
 	end
 	return interrupt
 end
 
-local getdigiline_send = function(pos)
+
+local function get_digiline_send(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)
@@ -193,145 +240,180 @@ local getdigiline_send = function(pos)
 	end
 end
 
-local create_environment = function(pos, mem, event)
+
+local safe_globals = {
+	"assert", "error", "ipairs", "next", "pairs", "pcall", "select",
+	"tonumber", "tostring", "type", "unpack", "_VERSION", "xpcall", 
+}
+local function create_environment(pos, mem, event)
 	-- Gather variables for the environment
 	local vports = minetest.registered_nodes[minetest.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)
-
-	return {
-			print = safe_print,
-			pin = merge_portstates(vports, rports),
-			port = vports,
-			interrupt = getinterrupt(pos),
-			digiline_send = getdigiline_send(pos),
-			mem = mem,
-			tostring = tostring,
-			tonumber = tonumber,
-			heat = minetest.get_meta(pos):get_int("heat"),
-			heat_max = OVERHEAT_MAX,
-			string = {
-				byte = string.byte,
-				char = string.char,
-				find = string.find,
-				format = string.format,
-				gmatch = string.gmatch,
-				gsub = string.gsub,
-				len = string.len,
-				lower = string.lower,
-				upper = string.upper,
-				match = string.match,
-				rep = string.rep,
-				reverse = string.reverse,
-				sub = string.sub,
-			},
-			math = {
-				abs = math.abs,
-				acos = math.acos,
-				asin = math.asin,
-				atan = math.atan,
-				atan2 = math.atan2,
-				ceil = math.ceil,
-				cos = math.cos,
-				cosh = math.cosh,
-				deg = math.deg,
-				exp = math.exp,
-				floor = math.floor,
-				fmod = math.fmod,
-				frexp = math.frexp,
-				huge = math.huge,
-				ldexp = math.ldexp,
-				log = math.log,
-				log10 = math.log10,
-				max = math.max,
-				min = math.min,
-				modf = math.modf,
-				pi = math.pi,
-				pow = math.pow,
-				rad = math.rad,
-				random = math.random,
-				sin = math.sin,
-				sinh = math.sinh,
-				sqrt = math.sqrt,
-				tan = math.tan,
-				tanh = math.tanh,
-			},
-			table = {
-				insert = table.insert,
-				maxn = table.maxn,
-				remove = table.remove,
-				sort = table.sort
-			},
-			event = event,
+	local vports_copy = {}
+	for k, v in pairs(vports) do vports_copy[k] = v end
+	local rports = get_real_port_states(pos)
+
+	-- Create new library tables on each call to prevent one LuaController
+	-- from breaking a library and messing up other LuaControllers.
+	local env = {
+		pin = merge_port_states(vports, rports),
+		port = vports_copy,
+		event = event,
+		mem = mem,
+		heat = minetest.get_meta(pos):get_int("heat"),
+		heat_max = OVERHEAT_MAX,
+		print = safe_print,
+		interrupt = get_interrupt(pos),
+		digiline_send = get_digiline_send(pos),
+		string = {
+			byte = string.byte,
+			char = string.char,
+			format = string.format,
+			gsub = string.gsub,
+			len = string.len,
+			lower = string.lower,
+			upper = string.upper,
+			rep = string.rep,
+			reverse = string.reverse,
+			sub = string.sub,
+		},
+		math = {
+			abs = math.abs,
+			acos = math.acos,
+			asin = math.asin,
+			atan = math.atan,
+			atan2 = math.atan2,
+			ceil = math.ceil,
+			cos = math.cos,
+			cosh = math.cosh,
+			deg = math.deg,
+			exp = math.exp,
+			floor = math.floor,
+			fmod = math.fmod,
+			frexp = math.frexp,
+			huge = math.huge,
+			ldexp = math.ldexp,
+			log = math.log,
+			log10 = math.log10,
+			max = math.max,
+			min = math.min,
+			modf = math.modf,
+			pi = math.pi,
+			pow = math.pow,
+			rad = math.rad,
+			random = math.random,
+			sin = math.sin,
+			sinh = math.sinh,
+			sqrt = math.sqrt,
+			tan = math.tan,
+			tanh = math.tanh,
+		},
+		table = {
+			concat = table.concat,
+			insert = table.insert,
+			maxn = table.maxn,
+			remove = table.remove,
+			sort = table.sort,
+		},
+		os = {
+			clock = os.clock,
+			difftime = os.difftime,
+			time = os.time,
+		},
 	}
+	env._G = env
+
+	for _, name in pairs(safe_globals) do
+		env[name] = _G[name]
+	end
+
+	return env
 end
 
-local create_sandbox = function (code, env)
-	-- Create Sandbox
+
+local function timeout()
+	debug.sethook()  -- Clear hook
+	error("Code timed out!")
+end
+
+
+local function code_prohibited(code)
+	-- LuaJIT doesn't increment the instruction counter when running
+	-- loops, so we have to sanitize inputs if we're using LuaJIT.
+	if not jit then
+		return false
+	end
+	local prohibited = {"while", "for", "do", "repeat", "until", "goto"}
+	code = " "..code.." "
+	for _, p in ipairs(prohibited) do
+		if string.find(code, "[^%w_]"..p.."[^%w_]") then
+			return "Prohibited command: "..p
+		end
+	end
+end
+
+
+local function create_sandbox(code, env)
 	if code:byte(1) == 27 then
-		return _, "You Hacker You! Don't use binary code!"
+		return nil, "Binary code prohibited."
 	end
-	f, msg = loadstring(code)
-	if not f then return _, msg end
+	local f, msg = loadstring(code)
+	if not f then return nil, msg end
 	setfenv(f, env)
-	return f
-end
 
-local lc_overheat = function (pos, meta)
-	if mesecon.do_overheat(pos) then -- if too hot
-		local node = minetest.get_node(pos)
-		minetest.swap_node(pos, {name = BASENAME.."_burnt", param2 = node.param2})
-		minetest.after(0.2, overheat_off, pos) -- wait for pending operations
-		return true
+	return function(...)
+		debug.sethook(timeout, "", 10000)
+		local ok, ret = pcall(f, ...)
+		debug.sethook()  -- Clear hook
+		if not ok then error(ret) end
+		return ret
 	end
 end
 
-local load_memory = function(meta)
+
+local function load_memory(meta)
 	return minetest.deserialize(meta:get_string("lc_memory")) or {}
 end
 
-local save_memory = function(meta, mem)
-	meta:set_string("lc_memory", safe_serialize(mem))
-end
 
-local ports_invalid = function (var)
-	if type(var) == "table" then
-		return false
-	end
-	return "The ports you set are invalid"
+local function save_memory(meta, mem)
+	meta:set_string("lc_memory",
+		minetest.serialize(
+			remove_functions(mem)
+		)
+	)
 end
 
-----------------------
--- Parsing function --
-----------------------
 
-lc_update = function (pos, event)
+local function run(pos, event)
 	local meta = minetest.get_meta(pos)
-	if lc_overheat(pos) then return end
+	if overheat(pos) then return end
 
-	-- load code & mem from memory
+	-- Load code & mem from meta
 	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 err = code_prohibited(code)
+	if err then return err end
+
+	-- Create environment
 	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
+	-- Create the sandbox and execute code
+	local f, msg = create_sandbox(code, env)
+	if not f then return msg end
 	local success, msg = pcall(f)
 	if not success then return msg end
-	if ports_invalid(env.port) then return ports_invalid(env.port) end
+	if type(env.port) ~= "table" then
+		return "Ports set are invalid."
+	end
 
-	save_memory(meta, mem)
+	save_memory(meta, env.mem)
 
 	-- Actually set the ports
-	action(pos, env.port)
+	set_port_states(pos, env.port)
 end
 
-local reset_meta = function(pos, code, errmsg)
+local function reset_meta(pos, code, errmsg)
 	local meta = minetest.get_meta(pos)
 	meta:set_string("code", code)
 	code = minetest.formspec_escape(code or "")
@@ -343,173 +425,164 @@ 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))
+	meta:set_int("luac_id", math.random(1, 65535))
 end
 
-local reset = function (pos)
-	action(pos, {a=false, b=false, c=false, d=false})
+local function reset(pos)
+	set_port_states(pos, {a=false, b=false, c=false, d=false})
 end
 
---        ______
---       |
---       |
---       |        __       ___  _   __         _  _
--- |   | |       |  | |\ |  |  |_| |  | |  |  |_ |_|
--- |___| |______ |__| | \|  |  | \ |__| |_ |_ |_ |\
--- |
--- |
---
+
+mesecon.queue:add_function("LuaController 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
+	run(pos, {type="interrupt", iid = iid})
+end)
+
 
 -----------------------
 -- Node Registration --
 -----------------------
 
-local output_rules={}
-local input_rules={}
+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 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
 	}
+}
 
-local selectionbox = {
-		type = "fixed",
-		fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
-	}
+local selection_box = {
+	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", channel = channel, msg = msg})
+		action = function(pos, node, channel, msg)
+			run(pos, {type = "digiline", channel = channel, msg = msg})
 		end
 	}
 }
+local function on_receive_fields(pos, form_name, fields)
+	if not fields.program then
+		return
+	end
+	reset(pos)
+	reset_meta(pos, fields.code)
+	local err = run(pos, {type="program"})
+	if err then
+		print(err)
+		reset_meta(pos, fields.code, err)
+	end
+end
 
-for a = 0, 1 do -- 0 = off; 1 = on
+for a = 0, 1 do -- 0 = off  1 = on
 for b = 0, 1 do
 for c = 0, 1 do
 for d = 0, 1 do
+	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
 
-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"
-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, overheat = 1}
-else
-	groups = {dig_immediate=2, overheat = 1}
-end
+	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
 
-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, _, rulename, newstate)
-			lc_update_real_portstates(pos, rulename, newstate)
-			lc_update(pos, {type=newstate,  pin=rulename})
-		end,
-	},
-	receptor =
-	{
-		state = mesecon.state.on,
-		rules = output_rules[cid]
+	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)
+				run(pos, {type=new_state,  pin=rule_name})
+			end,
+		},
+		receptor = {
+			state = mesecon.state.on,
+			rules = output_rules[cid]
+		}
 	}
-}
 
-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"
+	minetest.register_node(node_name, {
+		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"
 		},
-
-	inventory_image = top,
-	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)
-		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)
-			reset_meta(pos, fields.code, err)
-		end
-	end,
-	on_timer = handle_timer,
-	sounds = default.node_sound_stone_defaults(),
-	mesecons = mesecons,
-	digiline = digiline,
-	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,
-	is_luacontroller = true,
-})
+		inventory_image = top,
+		paramtype = "light",
+		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,
+		on_timer = handle_timer,
+		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)
+			mesecon:receptor_off(pos, output_rules)
+		end,
+		is_luacontroller = true,
+	})
 end
 end
 end
 end
 
 ------------------------------
--- overheated luacontroller --
+-- Overheated LuaController --
 ------------------------------
 
-local mesecons_burnt = {
-	effector =
-	{
-		rules = mesecon.rules.flat,
-		action_change = function (pos, _, rulename, newstate)
-			-- only update portstates when changes are triggered
-			lc_update_real_portstates(pos, rulename, newstate)
-		end
-	}
-}
-
 minetest.register_node(BASENAME .. "_burnt", {
 	drawtype = "nodebox",
 	tiles = {
@@ -528,21 +601,17 @@ minetest.register_node(BASENAME .. "_burnt", {
 	selection_box = selectionbox,
 	node_box = nodebox,
 	on_construct = reset_meta,
-	on_receive_fields = function(pos, formname, fields)
-		if fields.quit then
-			return
-		end
-		reset(pos)
-		reset_meta(pos, fields.code)
-		local err = lc_update(pos, {type="program"})
-		if err then
-			print(err)
-			reset_meta(pos, fields.code, err)
-		end
-	end,
+	on_receive_fields = on_receive_fields,
 	sounds = default.node_sound_stone_defaults(),
 	virtual_portstates = {a = false, b = false, c = false, d = false},
-	mesecons = mesecons_burnt,
+	mesecons = {
+		effector = {
+			rules = mesecon.rules.flat,
+			action_change = function(pos, _, rule_name, new_state)
+				update_real_portstates(pos, rule_name, new_state)
+			end,
+		},
+	},
 })
 
 ------------------------
diff --git a/mesecons_microcontroller/init.lua b/mesecons_microcontroller/init.lua
index 8c9f3b8c402aa23716e77b96a7208c7e7f3598d3..2cea23c7faf6b98e54daccc962cbf7b0ea1ee508 100644
--- a/mesecons_microcontroller/init.lua
+++ b/mesecons_microcontroller/init.lua
@@ -638,7 +638,7 @@ function yc_update_real_portstates(pos, node, rulename, newstate)
 	end
 	local n = meta:get_int("real_portstates") - 1
 	if n < 0 then
-		legacy_update_ports(pos)
+		mesecon.legacy_update_ports(pos)
 		n = meta:get_int("real_portstates") - 1
 	end
 	local L = {}
@@ -663,7 +663,7 @@ function yc_get_real_portstates(pos) -- determine if ports are powered (by itsel
 	local L = {}
 	local n = meta:get_int("real_portstates") - 1
 	if n < 0 then
-		return legacy_update_ports(pos)
+		return mesecon.legacy_update_ports(pos)
 	end
 	for _, index in ipairs({"a", "b", "c", "d"}) do
 		L[index] = ((n%2) == 1)