forked from minetest-mods/mesecons
		
	Remove timer() from LuaController and make interrupt() use the ActionQueue so that it will keep working when restarting the server
This commit is contained in:
		@@ -6,18 +6,18 @@ end
 | 
			
		||||
 | 
			
		||||
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
 | 
			
		||||
-- use overwritecheck nil to never overwrite, but just add the event to the queue
 | 
			
		||||
-- priority specifies the order actions are executed within one globalstep, highest by default
 | 
			
		||||
-- priority specifies the order actions are executed within one globalstep, highest first
 | 
			
		||||
-- should be between 0 and 1
 | 
			
		||||
function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
 | 
			
		||||
	-- Create Action Table:
 | 
			
		||||
	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
 | 
			
		||||
	priority = priority or 1
 | 
			
		||||
	action = {	pos=mesecon:tablecopy(pos),
 | 
			
		||||
			func=func,
 | 
			
		||||
			params=mesecon:tablecopy(params),
 | 
			
		||||
			time=time,
 | 
			
		||||
			owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil,
 | 
			
		||||
			priority=priority}
 | 
			
		||||
	local action = {	pos=mesecon:tablecopy(pos),
 | 
			
		||||
				func=func,
 | 
			
		||||
				params=mesecon:tablecopy(params),
 | 
			
		||||
				time=time,
 | 
			
		||||
				owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil,
 | 
			
		||||
				priority=priority}
 | 
			
		||||
 | 
			
		||||
	-- if not using the queue, (MESECONS_GLOBALSTEP off), just execute the function an we're done
 | 
			
		||||
	if not MESECONS_GLOBALSTEP and action.time == 0 then
 | 
			
		||||
@@ -50,7 +50,7 @@ end
 | 
			
		||||
-- However, even that does not work in some cases, that's why we delay the time the globalsteps
 | 
			
		||||
-- start to be execute by 5 seconds
 | 
			
		||||
local get_highest_priority = function (actions)
 | 
			
		||||
	local highestp = 0, highesti
 | 
			
		||||
	local highestp = -1, highesti
 | 
			
		||||
	for i, ac in ipairs(actions) do
 | 
			
		||||
		if ac.priority > highestp then
 | 
			
		||||
			highestp = ac.priority
 | 
			
		||||
@@ -70,7 +70,8 @@ minetest.register_globalstep(function (dtime)
 | 
			
		||||
 | 
			
		||||
	mesecon.queue.actions = {}
 | 
			
		||||
 | 
			
		||||
	-- sort actions in execute now (actions_now) and for later (mesecon.queue.actions)
 | 
			
		||||
	-- sort actions into two categories:
 | 
			
		||||
	-- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions)
 | 
			
		||||
	for i, ac in ipairs(actions) do
 | 
			
		||||
		if ac.time > 0 then
 | 
			
		||||
			ac.time = ac.time - dtime -- executed later
 | 
			
		||||
 
 | 
			
		||||
@@ -192,48 +192,21 @@ 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 handle_timer = function(pos, elapsed)
 | 
			
		||||
	local err = lc_update(pos, {type="timer"})
 | 
			
		||||
	if err then print(err) end
 | 
			
		||||
	return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local gettimer = function(pos)
 | 
			
		||||
	local timer = function (time)
 | 
			
		||||
		if type(time) ~= "number" then return end
 | 
			
		||||
		local nodetimer = minetest.get_node_timer(pos)
 | 
			
		||||
		nodetimer:start(time)
 | 
			
		||||
	end
 | 
			
		||||
	return timer
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local getdigiline_send = function(pos)
 | 
			
		||||
	if not digiline then return end
 | 
			
		||||
	-- Send messages on next serverstep
 | 
			
		||||
@@ -255,7 +228,6 @@ local create_environment = function(pos, mem, event)
 | 
			
		||||
			pin = merge_portstates(vports, rports),
 | 
			
		||||
			port = vports,
 | 
			
		||||
			interrupt = getinterrupt(pos),
 | 
			
		||||
			timer = gettimer(pos),
 | 
			
		||||
			digiline_send = getdigiline_send(pos),
 | 
			
		||||
			mem = mem,
 | 
			
		||||
			tostring = tostring,
 | 
			
		||||
@@ -334,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
 | 
			
		||||
@@ -348,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
 | 
			
		||||
@@ -375,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
 | 
			
		||||
@@ -412,10 +368,10 @@ 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})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -541,14 +497,15 @@ minetest.register_node(nodename, {
 | 
			
		||||
		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
 | 
			
		||||
@@ -556,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
 | 
			
		||||
@@ -588,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},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user