diff options
| -rw-r--r-- | mesecons/actionqueue.lua | 28 | ||||
| -rw-r--r-- | mesecons/init.lua | 14 | ||||
| -rw-r--r-- | mesecons/internal.lua | 58 | ||||
| -rw-r--r-- | mesecons/services.lua | 6 | ||||
| -rw-r--r-- | mesecons/util.lua | 1 | 
5 files changed, 63 insertions, 44 deletions
| diff --git a/mesecons/actionqueue.lua b/mesecons/actionqueue.lua index 9d31426..a00054a 100644 --- a/mesecons/actionqueue.lua +++ b/mesecons/actionqueue.lua @@ -6,15 +6,19 @@ 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 -function mesecon.queue:add_action(pos, func, params, time, overwritecheck) +-- priority specifies the order actions are executed within one globalstep, highest by default +-- 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  	overwritecheck = overwritecheck or {}  	action = {	pos=mesecon:tablecopy(pos),  			func=func,  			params=mesecon:tablecopy(params),  			time=time, -			owcheck=mesecon:tablecopy(overwritecheck)} +			owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil, +			priority=priority}  	--print(dump(action))  	-- if not using the queue, (MESECONS_GLOBALSTEP off), just execute the function an we're done @@ -42,6 +46,18 @@ end  -- this makes sure that resuming mesecons circuits when restarting minetest works fine  -- 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 +	for i, ac in ipairs(actions) do +		if ac.priority > highestp then +			highestp = ac.priority +			highesti = i +		end +	end + +	return highesti +end +  local m_time = 0  minetest.register_globalstep(function (dtime)  	m_time = m_time + dtime @@ -53,10 +69,14 @@ minetest.register_globalstep(function (dtime)  		if action.time > 0 then  			action.time = action.time - dtime  			table.insert(mesecon.queue.actions, action) -- will be handled another time -		else -- execute and remove -			mesecon.queue:execute(action)  		end  	end + +	while(#actions > 0) do -- execute highest priorities first, until all are executed +		local hp = get_highest_priority(actions) +		mesecon.queue:execute(actions[hp]) +		table.remove(actions, hp) +	end  end)  function mesecon.queue:execute(action) diff --git a/mesecons/init.lua b/mesecons/init.lua index 8facf73..4d4819c 100644 --- a/mesecons/init.lua +++ b/mesecons/init.lua @@ -79,12 +79,18 @@ dofile(minetest.get_modpath("mesecons").."/legacy.lua");  mesecon.queue:add_function("receptor_on", function (pos, rules)  	rules = rules or mesecon.rules.default +	-- if area (any of the neighbors) is not loaded, keep trying and call this again later  	for _, rule in ipairs(mesecon:flattenrules(rules)) do  		local np = mesecon:addPosRule(pos, rule) -		-- if area is not loaded, keep trying -		if minetest.env:get_node_or_nil(np) == nil then +		if minetest.get_node_or_nil(np) == nil then  			mesecon.queue:add_action(pos, "receptor_on", {rules}) +			return  		end +	end + +	-- execute action +	for _, rule in ipairs(mesecon:flattenrules(rules)) do +		local np = mesecon:addPosRule(pos, rule)  		local rulenames = mesecon:rules_link_rule_all(pos, rule)  		for _, rulename in ipairs(rulenames) do  			mesecon:turnon(np, rulename) @@ -100,7 +106,7 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)  	rules = rules or mesecon.rules.default  	for _, rule in ipairs(mesecon:flattenrules(rules)) do  		local np = mesecon:addPosRule(pos, rule) -		if minetest.env:get_node_or_nil(np) == nil then +		if minetest.get_node_or_nil(np) == nil then  			mesecon.queue:add_action(pos, "receptor_off", {rules})  		end  		local rulenames = mesecon:rules_link_rule_all(pos, rule) @@ -108,7 +114,7 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)  			if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then  				mesecon:turnoff(np, rulename)  			else -				mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off) +				mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 1)  			end  		end  	end diff --git a/mesecons/internal.lua b/mesecons/internal.lua index f575c83..f713a7c 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -22,9 +22,9 @@  -- mesecon:effector_get_rules(node)  --> Returns the input rules of the effector (mesecon.rules.default if none specified)  -- SIGNALS --- mesecon:activate(pos, node)     --> Activates   the effector node at the specific pos (calls nodedef.mesecons.effector.action_on) --- mesecon:deactivate(pos, node)   --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off) --- mesecon:changesignal(pos, node, rulename, newstate) --> Changes     the effector node at the specific pos (calls nodedef.mesecons.effector.action_change) +-- mesecon:activate(pos, node, recdepth)		--> Activates   the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher recdepths are executed later +-- mesecon:deactivate(pos, node, recdepth)		--> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), " +-- mesecon:changesignal(pos, node, rulename, newstate)	--> Changes     the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), "  -- RULES  -- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name @@ -41,8 +41,8 @@  -- HIGH-LEVEL Internals  -- mesecon:is_power_on(pos)             --> Returns true if pos emits power in any way  -- mesecon:is_power_off(pos)            --> Returns true if pos does not emit power in any way --- mesecon:turnon(pos, rulename)        --> Returns true  whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnon --- mesecon:turnoff(pos, rulename)       --> Turns off whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnoff +-- mesecon:turnon(pos, rulename)        --> Returns true  whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnon; Uses third parameter recdepth internally to determine how far away the current node is from the initial pos as it uses recursion +-- mesecon:turnoff(pos, rulename)       --> Turns off whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnoff; Uses third parameter recdepth internally to determine how far away the current node is from the initial pos as it uses recursion  -- mesecon:connected_to_receptor(pos)   --> Returns true if pos is connected to a receptor directly or via conductors; calls itself if pos is a conductor --> recursive  -- mesecon:rules_link(output, input, dug_outputrules) --> Returns true if outputposition + outputrules = inputposition and inputposition + inputrules = outputposition (if the two positions connect)  -- mesecon:rules_link_anydir(outp., inp., d_outpr.)   --> Same as rules mesecon:rules_link but also returns true if output and input are swapped @@ -191,14 +191,14 @@ mesecon.queue:add_function("activate", function (pos, rulename)  	end  end) -function mesecon:activate(pos, node, rulename) +function mesecon:activate(pos, node, rulename, recdepth)  	if rulename == nil then  		for _,rule in ipairs(mesecon:effector_get_rules(node)) do -			mesecon:activate(pos, node, rule) +			mesecon:activate(pos, node, rule, recdepth + 1)  		end  		return  	end -	mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename) +	mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / recdepth)  end @@ -212,14 +212,14 @@ mesecon.queue:add_function("deactivate", function (pos, rulename)  	end  end) -function mesecon:deactivate(pos, node, rulename) +function mesecon:deactivate(pos, node, rulename, recdepth)  	if rulename == nil then  		for _,rule in ipairs(mesecon:effector_get_rules(node)) do -			mesecon:deactivate(pos, node, rule) +			mesecon:deactivate(pos, node, rule, recdepth + 1)  		end  		return  	end -	mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename) +	mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / recdepth)  end @@ -233,15 +233,15 @@ mesecon.queue:add_function("change", function (pos, rulename, changetype)  	end  end) -function mesecon:changesignal(pos, node, rulename, newstate) +function mesecon:changesignal(pos, node, rulename, newstate, recdepth)  	if rulename == nil then  		for _,rule in ipairs(mesecon:effector_get_rules(node)) do -			mesecon:changesignal(pos, node, rule, newstate) +			mesecon:changesignal(pos, node, rule, newstate, recdepth + 1)  		end  		return  	end -	mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename) +	mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / recdepth)  end  -- ######### @@ -365,7 +365,8 @@ function mesecon:is_power_off(pos, rulename)  	return false  end -function mesecon:turnon(pos, rulename) +function mesecon:turnon(pos, rulename, recdepth) +	recdepth = recdepth or 2  	local node = minetest.get_node(pos)  	if mesecon:is_conductor_off(node, rulename) then @@ -374,7 +375,7 @@ function mesecon:turnon(pos, rulename)  		if not rulename then  			for _, rule in ipairs(mesecon:flattenrules(rules)) do  				if mesecon:connected_to_receptor(pos, rule) then -					mesecon:turnon(pos, rule) +					mesecon:turnon(pos, rule, recdepth + 1)  				end  			end  			return @@ -387,32 +388,23 @@ function mesecon:turnon(pos, rulename)  			local rulenames = mesecon:rules_link_rule_all(pos, rule)  			for _, rulename in ipairs(rulenames) do -				mesecon:turnon(np, rulename) +				mesecon:turnon(np, rulename, recdepth + 1)  			end  		end  	elseif mesecon:is_effector(node.name) then -		mesecon:changesignal(pos, node, rulename, mesecon.state.on) +		mesecon:changesignal(pos, node, rulename, mesecon.state.on, recdepth)  		if mesecon:is_effector_off(node.name) then -			mesecon:activate(pos, node, rulename) +			mesecon:activate(pos, node, rulename, recdepth)  		end  	end  end -function mesecon:turnoff(pos, rulename) +function mesecon:turnoff(pos, rulename, recdepth) +	recdepth = recdepth or 0  	local node = minetest.get_node(pos)  	if mesecon:is_conductor_on(node, rulename) then  		local rules = mesecon:conductor_get_rules(node) -		--[[ -		if not rulename then -			for _, rule in ipairs(mesecon:flattenrules(rules)) do -				if mesecon:is_powered(pos, rule) then -					mesecon:turnoff(pos, rule) -				end -			end -			return -		end -		--]]  		minetest.swap_node(pos, {name = mesecon:get_conductor_off(node, rulename), param2 = node.param2})  		for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do @@ -420,14 +412,14 @@ function mesecon:turnoff(pos, rulename)  			local rulenames = mesecon:rules_link_rule_all(pos, rule)  			for _, rulename in ipairs(rulenames) do -				mesecon:turnoff(np, rulename) +				mesecon:turnoff(np, rulename, recdepth + 1)  			end  		end  	elseif mesecon:is_effector(node.name) then -		mesecon:changesignal(pos, node, rulename, mesecon.state.off) +		mesecon:changesignal(pos, node, rulename, mesecon.state.off, recdepth)  		if mesecon:is_effector_on(node.name)  		and not mesecon:is_powered(pos) then -			mesecon:deactivate(pos, node, rulename) +			mesecon:deactivate(pos, node, rulename, recdepth + 1)  		end  	end  end diff --git a/mesecons/services.lua b/mesecons/services.lua index 29b5183..de0c8b6 100644 --- a/mesecons/services.lua +++ b/mesecons/services.lua @@ -6,13 +6,13 @@ mesecon.on_placenode = function (pos, node)  			mesecon:turnon (pos)  			--mesecon:receptor_on (pos, mesecon:conductor_get_rules(node))  		else -			mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on") -			mesecon:activate(pos, node) +			mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1) +			mesecon:activate(pos, node, nil, 1)  		end  	elseif mesecon:is_conductor_on(node) then  		minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)})  	elseif mesecon:is_effector_on (node.name) then -		mesecon:deactivate(pos, node) +		mesecon:deactivate(pos, node, nil, 1)  	end  end diff --git a/mesecons/util.lua b/mesecons/util.lua index ad2a4ae..91d435a 100644 --- a/mesecons/util.lua +++ b/mesecons/util.lua @@ -169,6 +169,7 @@ function mesecon:cmpSpecial(r1, r2)  end  function mesecon:tablecopy(table) -- deep table copy +	if type(table) ~= "table" then return table end -- no need to copy  	local newtable = {}  	for idx, item in pairs(table) do | 
