diff options
| -rw-r--r-- | mesecons_luacontroller/init.lua | 94 | 
1 files changed, 73 insertions, 21 deletions
diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index e3aa6fd..f24a8ad 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -26,6 +26,11 @@ rules.b = {x =  0, y = 0, z =  1}  rules.c = {x =  1, y = 0, z =  0}  rules.d = {x =  0, y = 0, z = -1} +------------------ +-- Action stuff -- +------------------ +-- These helpers are required to set the portstates of the luacontroller +  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)) @@ -80,7 +85,10 @@ local action = function (pos, ports)  	action_setports (pos, ports, vports)  end --- Overheat Stuff +-------------------- +-- Overheat stuff -- +-------------------- +  local heat = function (meta) -- warm up  	h = meta:get_int("heat")  	if h ~= nil then @@ -106,14 +114,14 @@ local overheat = function (meta) -- determine if too hot  end  local overheat_off = function(pos) -	rules = mesecon:get_rules("mesecons_microcontroller:microcontroller1111") -	mesecon:receptor_off(pos, rules) +	mesecon:receptor_off(pos, mesecon.rules.flat)  end -local update = function (pos) -	local meta = minetest.env:get_meta(pos) -	code = meta:get_string("code") +------------------- +-- Parsing stuff -- +------------------- +local code_prohibited = function(code)  	-- Clean code  	local prohibited = {"while", "for", "repeat", "until"}  	for _, p in ipairs(prohibited) do @@ -121,27 +129,36 @@ local update = function (pos)  			return "Prohibited command: "..p  		end  	end +end + +local safeprint = function(param) +	print(dump(param)) +end +local create_environment = function(pos, mem)  	-- Gather variables for the environment  	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}  	local rports = get_real_portstates(pos) -	local env = {	print = print, -				selfpos = pos, -				dump = dump, -				pin = merge_portstates(vports, rports), -				port = vports} +	return {	print = safeprint, +			pin = merge_portstates(vports, rports), +			port = vports, +			mem = mem} +end +local create_sandbox = function (code, env)  	-- Create Sandbox  	if code:byte(1) == 27 then -		return "You Hacker You! Don't use binary code!" +		return _, "You Hacker You! Don't use binary code!"  	end -	local f, msg = loadstring(code) -	if not f then return msg end +	f, msg = loadstring(code) +	if not f then return _, msg end  	setfenv(f, env) -	success, msg = pcall(f) +	return f +end +local do_overheat = function (pos, meta)  	-- Overheat protection  	heat(meta)  	minetest.after(0.5, cool, meta) @@ -151,13 +168,40 @@ local update = function (pos)  		minetest.env:add_item(pos, BASENAME.."0000")  		return  	end +end + +local load_memory = function(meta) +	return minetest.deserialize(meta:get_string("lc_memory")) or {} +end + +local save_memory = function(meta, mem) +	meta:set_string("lc_memory", minetest.serialize(mem)) +end + +---------------------- +-- Parsing function -- +---------------------- + +local update = function (pos) +	local meta = minetest.env:get_meta(pos) + +	local mem  = load_memory(meta) +	local code = meta:get_string("code") + +	local prohibited = code_prohibited(code) +	if 	prohibited then return prohibited end +	local env = create_environment(pos, mem) + +	local chunk, msg = create_sandbox (code, env) +	if not chunk then return msg end +	local success, msg = pcall(f) +	if not success then return msg end + +	do_overheat(pos, meta) +	save_memory(meta, mem)  	-- Actually set the ports -	if not success then -		return msg -	else -		action(pos, env.port) -	end +	action(pos, env.port)  end  local reset_meta = function(pos, code, errmsg) @@ -186,7 +230,10 @@ end  -- |     |       |  | |\ |  |  |_| |  | |  |  |_ |_|  -- |     |______ |__| | \|  |  | \ |__| |_ |_ |_ |\  -- --- Actually register all the stuff: + +----------------------- +-- Node Registration -- +-----------------------  for a = 0, 1 do  for b = 0, 1 do @@ -293,6 +340,10 @@ end  end  end +------------------------ +-- Craft Registration -- +------------------------ +  minetest.register_craft({  	output = BASENAME.."0000 2",  	recipe = { @@ -301,3 +352,4 @@ minetest.register_craft({  		{'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable', ''},  	}  }) +  | 
