forked from Mirrorlandia_minetest/mesecons
Merge branch 'actionqueue'
This introduces the ActionQueue, a new kind of MESECONS_GLOBALSTEP. Circuits using delayers will now resume when restarting the server. Also, large circuits should automatically resume if parts of them are in unloaded chunks. Old circuits e.g. using gates will not resume when mesecons is updated, which means you have to restart them once. But after that, it should work just like it used to. This will fix a lot of stuff but may also introduce some new bugs. So please report them!
This commit is contained in:
commit
8a71f51b26
119
mesecons/actionqueue.lua
Normal file
119
mesecons/actionqueue.lua
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
mesecon.queue.actions={} -- contains all ActionQueue actions
|
||||||
|
|
||||||
|
function mesecon.queue:add_function(name, func)
|
||||||
|
mesecon.queue.funcs[name] = func
|
||||||
|
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
|
||||||
|
-- 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}
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
mesecon.queue:execute(action)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local toremove = nil
|
||||||
|
-- Otherwise, add the action to the queue
|
||||||
|
if overwritecheck then -- check if old action has to be overwritten / removed:
|
||||||
|
for i, ac in ipairs(mesecon.queue.actions) do
|
||||||
|
if(mesecon:cmpPos(pos, ac.pos)
|
||||||
|
and mesecon:cmpAny(overwritecheck, ac.owcheck)) then
|
||||||
|
toremove = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (toremove ~= nil) then
|
||||||
|
table.remove(mesecon.queue.actions, toremove)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(mesecon.queue.actions, action)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- execute the stored functions on a globalstep
|
||||||
|
-- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function
|
||||||
|
-- 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
|
||||||
|
if (m_time < MESECONS_RESUMETIME) then return end -- don't even try if server has not been running for XY seconds
|
||||||
|
local actions = mesecon:tablecopy(mesecon.queue.actions)
|
||||||
|
local actions_now={}
|
||||||
|
|
||||||
|
mesecon.queue.actions = {}
|
||||||
|
|
||||||
|
-- sort actions in execute now (actions_now) and for later (mesecon.queue.actions)
|
||||||
|
for i, ac in ipairs(actions) do
|
||||||
|
if ac.time > 0 then
|
||||||
|
ac.time = ac.time - dtime -- executed later
|
||||||
|
table.insert(mesecon.queue.actions, ac)
|
||||||
|
else
|
||||||
|
table.insert(actions_now, ac)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
while(#actions_now > 0) do -- execute highest priorities first, until all are executed
|
||||||
|
local hp = get_highest_priority(actions_now)
|
||||||
|
mesecon.queue:execute(actions_now[hp])
|
||||||
|
table.remove(actions_now, hp)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function mesecon.queue:execute(action)
|
||||||
|
mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Store and read the ActionQueue to / from a file
|
||||||
|
-- so that upcoming actions are remembered when the game
|
||||||
|
-- is restarted
|
||||||
|
|
||||||
|
local wpath = minetest.get_worldpath()
|
||||||
|
local function file2table(filename)
|
||||||
|
local f = io.open(filename, "r")
|
||||||
|
if f==nil then return {} end
|
||||||
|
local t = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
if t=="" or t==nil then return {} end
|
||||||
|
return minetest.deserialize(t)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function table2file(filename, table)
|
||||||
|
local f = io.open(filename, "w")
|
||||||
|
f:write(minetest.serialize(table))
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
mesecon.queue.actions = file2table(wpath.."/mesecon_actionqueue")
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
mesecon.queue.actions = table2file(wpath.."/mesecon_actionqueue", mesecon.queue.actions)
|
||||||
|
end)
|
@ -42,37 +42,8 @@
|
|||||||
|
|
||||||
-- PUBLIC VARIABLES
|
-- PUBLIC VARIABLES
|
||||||
mesecon={} -- contains all functions and all global variables
|
mesecon={} -- contains all functions and all global variables
|
||||||
mesecon.actions_on={} -- Saves registered function callbacks for mesecon on | DEPRECATED
|
mesecon.queue={} -- contains the ActionQueue
|
||||||
mesecon.actions_off={} -- Saves registered function callbacks for mesecon off | DEPRECATED
|
mesecon.queue.funcs={} -- contains all ActionQueue functions
|
||||||
mesecon.actions_change={} -- Saves registered function callbacks for mesecon change | DEPRECATED
|
|
||||||
mesecon.receptors={} -- saves all information about receptors | DEPRECATED
|
|
||||||
mesecon.effectors={} -- saves all information about effectors | DEPRECATED
|
|
||||||
mesecon.conductors={} -- saves all information about conductors | DEPRECATED
|
|
||||||
|
|
||||||
|
|
||||||
local wpath = minetest.get_worldpath()
|
|
||||||
local function read_file(fn)
|
|
||||||
local f = io.open(fn, "r")
|
|
||||||
if f==nil then return {} end
|
|
||||||
local t = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
if t=="" or t==nil then return {} end
|
|
||||||
return minetest.deserialize(t)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function write_file(fn, tbl)
|
|
||||||
local f = io.open(fn, "w")
|
|
||||||
f:write(minetest.serialize(tbl))
|
|
||||||
f:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
mesecon.to_update = read_file(wpath.."/mesecon_to_update")
|
|
||||||
mesecon.r_to_update = read_file(wpath.."/mesecon_r_to_update")
|
|
||||||
|
|
||||||
minetest.register_on_shutdown(function()
|
|
||||||
write_file(wpath.."/mesecon_to_update",mesecon.to_update)
|
|
||||||
write_file(wpath.."/mesecon_r_to_update",mesecon.r_to_update)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Settings
|
-- Settings
|
||||||
dofile(minetest.get_modpath("mesecons").."/settings.lua")
|
dofile(minetest.get_modpath("mesecons").."/settings.lua")
|
||||||
@ -86,6 +57,10 @@ dofile(minetest.get_modpath("mesecons").."/presets.lua");
|
|||||||
-- mostly things that make the source look cleaner
|
-- mostly things that make the source look cleaner
|
||||||
dofile(minetest.get_modpath("mesecons").."/util.lua");
|
dofile(minetest.get_modpath("mesecons").."/util.lua");
|
||||||
|
|
||||||
|
-- The ActionQueue
|
||||||
|
-- Saves all the actions that have to be execute in the future
|
||||||
|
dofile(minetest.get_modpath("mesecons").."/actionqueue.lua");
|
||||||
|
|
||||||
-- Internal stuff
|
-- Internal stuff
|
||||||
-- This is the most important file
|
-- This is the most important file
|
||||||
-- it handles signal transmission and basically everything else
|
-- it handles signal transmission and basically everything else
|
||||||
@ -101,9 +76,22 @@ dofile(minetest.get_modpath("mesecons").."/legacy.lua");
|
|||||||
-- API
|
-- API
|
||||||
-- these are the only functions you need to remember
|
-- these are the only functions you need to remember
|
||||||
|
|
||||||
function mesecon:receptor_on_i(pos, rules)
|
mesecon.queue:add_function("receptor_on", function (pos, rules)
|
||||||
rules = rules or mesecon.rules.default
|
rules = rules or mesecon.rules.default
|
||||||
|
|
||||||
|
-- if area (any of the rule targets) is not loaded, keep trying and call this again later
|
||||||
|
if MESECONS_GLOBALSTEP then -- trying to enable resuming with globalstep disabled would cause an endless loop
|
||||||
|
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
||||||
|
local np = mesecon:addPosRule(pos, rule)
|
||||||
|
-- if area is not loaded, keep trying
|
||||||
|
if minetest.get_node_or_nil(np) == nil then
|
||||||
|
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- execute action
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local np = mesecon:addPosRule(pos, rule)
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
||||||
@ -111,19 +99,26 @@ function mesecon:receptor_on_i(pos, rules)
|
|||||||
mesecon:turnon(np, rulename)
|
mesecon:turnon(np, rulename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
function mesecon:receptor_on(pos, rules)
|
function mesecon:receptor_on(pos, rules)
|
||||||
if MESECONS_GLOBALSTEP then
|
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
|
||||||
rules = rules or mesecon.rules.default
|
|
||||||
mesecon.r_to_update[#mesecon.r_to_update+1]={pos=pos, rules=rules, action="on"}
|
|
||||||
else
|
|
||||||
mesecon:receptor_on_i(pos, rules)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:receptor_off_i(pos, rules)
|
mesecon.queue:add_function("receptor_off", function (pos, rules)
|
||||||
rules = rules or mesecon.rules.default
|
rules = rules or mesecon.rules.default
|
||||||
|
|
||||||
|
-- if area (any of the rule targets) is not loaded, keep trying and call this again later
|
||||||
|
if MESECONS_GLOBALSTEP then
|
||||||
|
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
||||||
|
local np = mesecon:addPosRule(pos, rule)
|
||||||
|
if minetest.get_node_or_nil(np) == nil then
|
||||||
|
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local np = mesecon:addPosRule(pos, rule)
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
||||||
@ -131,19 +126,14 @@ function mesecon:receptor_off_i(pos, rules)
|
|||||||
if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then
|
if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then
|
||||||
mesecon:turnoff(np, rulename)
|
mesecon:turnoff(np, rulename)
|
||||||
else
|
else
|
||||||
mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off)
|
mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
function mesecon:receptor_off(pos, rules)
|
function mesecon:receptor_off(pos, rules)
|
||||||
if MESECONS_GLOBALSTEP then
|
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
|
||||||
rules = rules or mesecon.rules.default
|
|
||||||
mesecon.r_to_update[#mesecon.r_to_update+1]={pos=pos, rules=rules, action="off"}
|
|
||||||
else
|
|
||||||
mesecon:receptor_off_i(pos, rules)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
|
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
|
||||||
|
|
||||||
-- SIGNALS
|
-- SIGNALS
|
||||||
-- mesecon:activate(pos, node) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on)
|
-- 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) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off)
|
-- 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)
|
-- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), "
|
||||||
|
|
||||||
-- RULES
|
-- RULES
|
||||||
-- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name
|
-- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name
|
||||||
@ -41,8 +41,8 @@
|
|||||||
-- HIGH-LEVEL Internals
|
-- HIGH-LEVEL Internals
|
||||||
-- mesecon:is_power_on(pos) --> Returns true if pos emits power in any way
|
-- 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: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: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
|
-- 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: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(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
|
-- mesecon:rules_link_anydir(outp., inp., d_outpr.) --> Same as rules mesecon:rules_link but also returns true if output and input are swapped
|
||||||
@ -177,121 +177,76 @@ function mesecon:effector_get_rules(node)
|
|||||||
return mesecon.rules.default
|
return mesecon.rules.default
|
||||||
end
|
end
|
||||||
|
|
||||||
--Signals
|
-- #######################
|
||||||
|
-- # Signals (effectors) #
|
||||||
|
-- #######################
|
||||||
|
|
||||||
function mesecon:activate(pos, node, rulename)
|
-- Activation:
|
||||||
if MESECONS_GLOBALSTEP then
|
mesecon.queue:add_function("activate", function (pos, rulename)
|
||||||
if rulename == nil then
|
node = minetest.get_node(pos)
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
effector = mesecon:get_effector(node.name)
|
||||||
mesecon:activate(pos, node, rule)
|
|
||||||
end
|
if effector and effector.action_on then
|
||||||
return
|
effector.action_on(pos, node, rulename)
|
||||||
end
|
|
||||||
add_action(pos, "on", rulename)
|
|
||||||
else
|
|
||||||
local effector = mesecon:get_effector(node.name)
|
|
||||||
if effector and effector.action_on then
|
|
||||||
effector.action_on (pos, node, rulename)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
function mesecon:deactivate(pos, node, rulename)
|
function mesecon:activate(pos, node, rulename, recdepth)
|
||||||
if MESECONS_GLOBALSTEP then
|
if rulename == nil then
|
||||||
if rulename == nil then
|
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
mesecon:activate(pos, node, rule, recdepth + 1)
|
||||||
mesecon:deactivate(pos, node, rule)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
add_action(pos, "off", rulename)
|
|
||||||
else
|
|
||||||
local effector = mesecon:get_effector(node.name)
|
|
||||||
if effector and effector.action_off then
|
|
||||||
effector.action_off (pos, node, rulename)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:changesignal(pos, node, rulename, newstate)
|
|
||||||
|
|
||||||
newstate = newstate or "on"
|
|
||||||
--rulename = rulename or mesecon.rules.default
|
|
||||||
if MESECONS_GLOBALSTEP then
|
|
||||||
if rulename == nil then
|
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
|
||||||
mesecon:changesignal(pos, node, rule, newstate)
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
|
||||||
add_action(pos, "c"..newstate, rulename)
|
|
||||||
else
|
|
||||||
local effector = mesecon:get_effector(node.name)
|
|
||||||
if effector and effector.action_change then
|
|
||||||
effector.action_change (pos, node, rulename, newstate)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / recdepth)
|
||||||
end
|
end
|
||||||
|
|
||||||
function execute_actions(dtime)
|
|
||||||
local nactions = mesecon.to_update
|
-- Deactivation
|
||||||
mesecon.to_update = {}
|
mesecon.queue:add_function("deactivate", function (pos, rulename)
|
||||||
for _,i in ipairs(nactions) do
|
node = minetest.get_node(pos)
|
||||||
node = minetest.get_node(i.pos)
|
effector = mesecon:get_effector(node.name)
|
||||||
if node.name=="ignore" then
|
|
||||||
add_action(i.pos, i.action, i.rname)
|
if effector and effector.action_off then
|
||||||
else
|
effector.action_off(pos, node, rulename)
|
||||||
effector = mesecon:get_effector(node.name)
|
|
||||||
if i.action == "on" then
|
|
||||||
if effector and effector.action_on then
|
|
||||||
effector.action_on(i.pos, node, i.rname)
|
|
||||||
end
|
|
||||||
elseif i.action == "off" then
|
|
||||||
if effector and effector.action_off then
|
|
||||||
effector.action_off(i.pos, node, i.rname)
|
|
||||||
end
|
|
||||||
elseif i.action == "con" then
|
|
||||||
if effector and effector.action_change then
|
|
||||||
effector.action_change(i.pos, node, i.rname, "on")
|
|
||||||
end
|
|
||||||
elseif i.action == "coff" then
|
|
||||||
if effector and effector.action_change then
|
|
||||||
effector.action_change(i.pos, node, i.rname, "off")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local nactions = mesecon.r_to_update
|
end)
|
||||||
mesecon.r_to_update = {}
|
|
||||||
for _,i in ipairs(nactions) do
|
function mesecon:deactivate(pos, node, rulename, recdepth)
|
||||||
if i.action == "on" then
|
if rulename == nil then
|
||||||
mesecon:receptor_on_i(i.pos, i.rules)
|
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
||||||
else
|
mesecon:deactivate(pos, node, rule, recdepth + 1)
|
||||||
mesecon:receptor_off_i(i.pos,i.rules)
|
|
||||||
end
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / recdepth)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_globalstep(execute_actions)
|
|
||||||
|
|
||||||
function add_action(pos, action, rname)
|
-- Change
|
||||||
for _,i in ipairs(mesecon.to_update) do
|
mesecon.queue:add_function("change", function (pos, rulename, changetype)
|
||||||
if i.pos.x == pos.x and i.pos.y == pos.y and i.pos.z == pos.z and i.rname.x == rname.x and i.rname.y == rname.y and i.rname.z == rname.z then
|
node = minetest.get_node(pos)
|
||||||
if (i.action == "on" and action == "on") or (i.action == "off" and action == "off") then
|
effector = mesecon:get_effector(node.name)
|
||||||
--nothing
|
|
||||||
elseif i.action == "coff" and action == "on" then i.action = "on"
|
if effector and effector.action_change then
|
||||||
elseif i.action == "con" and action == "off" then i.action = "off"
|
effector.action_change(pos, node, rulename, changetype)
|
||||||
else
|
|
||||||
if action == "on" or action == "con" then i.action = "con" end
|
|
||||||
if action == "off" or action == "coff" then i.action = "coff" end
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
mesecon.to_update[#mesecon.to_update+1] = {pos = pos, action = action, rname = rname}
|
end)
|
||||||
|
|
||||||
|
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, recdepth + 1)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / recdepth)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Rules
|
-- #########
|
||||||
|
-- # Rules # "Database" for rulenames
|
||||||
|
-- #########
|
||||||
|
|
||||||
function mesecon:add_rules(name, rules)
|
function mesecon:add_rules(name, rules)
|
||||||
mesecon.rules[name] = rules
|
mesecon.rules[name] = rules
|
||||||
@ -410,8 +365,15 @@ function mesecon:is_power_off(pos, rulename)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:turnon(pos, rulename)
|
function mesecon:turnon(pos, rulename, recdepth)
|
||||||
|
recdepth = recdepth or 2
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
|
|
||||||
|
if(node.name == "ignore") then
|
||||||
|
-- try turning on later again
|
||||||
|
mesecon.queue:add_action(
|
||||||
|
pos, "turnon", {rulename, recdepth + 1}, nil, true)
|
||||||
|
end
|
||||||
|
|
||||||
if mesecon:is_conductor_off(node, rulename) then
|
if mesecon:is_conductor_off(node, rulename) then
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
local rules = mesecon:conductor_get_rules(node)
|
||||||
@ -419,7 +381,7 @@ function mesecon:turnon(pos, rulename)
|
|||||||
if not rulename then
|
if not rulename then
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
||||||
if mesecon:connected_to_receptor(pos, rule) then
|
if mesecon:connected_to_receptor(pos, rule) then
|
||||||
mesecon:turnon(pos, rule)
|
mesecon:turnon(pos, rule, recdepth + 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
@ -429,54 +391,75 @@ function mesecon:turnon(pos, rulename)
|
|||||||
|
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local np = mesecon:addPosRule(pos, rule)
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
if(minetest.get_node(np).name == "ignore") then
|
||||||
|
-- try turning on later again
|
||||||
|
mesecon.queue:add_action(
|
||||||
|
np, "turnon", {rulename, recdepth + 1}, nil, true)
|
||||||
|
else
|
||||||
|
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
||||||
|
|
||||||
for _, rulename in ipairs(rulenames) do
|
for _, rulename in ipairs(rulenames) do
|
||||||
mesecon:turnon(np, rulename)
|
mesecon:turnon(np, rulename, recdepth + 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif mesecon:is_effector(node.name) then
|
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
|
if mesecon:is_effector_off(node.name) then
|
||||||
mesecon:activate(pos, node, rulename)
|
mesecon:activate(pos, node, rulename, recdepth)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:turnoff(pos, rulename)
|
mesecon.queue:add_function("turnon", function (pos, rulename, recdepth)
|
||||||
|
if (MESECONS_GLOBALSTEP) then -- do not resume if we don't use globalstep - that would cause an endless loop
|
||||||
|
mesecon:turnon(pos, rulename, recdepth)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function mesecon:turnoff(pos, rulename, recdepth)
|
||||||
|
recdepth = recdepth or 2
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
|
|
||||||
|
if(node.name == "ignore") then
|
||||||
|
-- try turning on later again
|
||||||
|
mesecon.queue:add_action(
|
||||||
|
pos, "turnoff", {rulename, recdepth + 1}, nil, true)
|
||||||
|
end
|
||||||
|
|
||||||
if mesecon:is_conductor_on(node, rulename) then
|
if mesecon:is_conductor_on(node, rulename) then
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
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})
|
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node, rulename), param2 = node.param2})
|
||||||
|
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local np = mesecon:addPosRule(pos, rule)
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
if(minetest.get_node(np).name == "ignore") then
|
||||||
|
-- try turning on later again
|
||||||
|
mesecon.queue:add_action(
|
||||||
|
np, "turnoff", {rulename, recdepth + 1}, nil, true)
|
||||||
|
else
|
||||||
|
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
||||||
|
|
||||||
for _, rulename in ipairs(rulenames) do
|
for _, rulename in ipairs(rulenames) do
|
||||||
mesecon:turnoff(np, rulename)
|
mesecon:turnoff(np, rulename, recdepth + 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif mesecon:is_effector(node.name) then
|
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)
|
if mesecon:is_effector_on(node.name)
|
||||||
and not mesecon:is_powered(pos) then
|
and not mesecon:is_powered(pos) then
|
||||||
mesecon:deactivate(pos, node, rulename)
|
mesecon:deactivate(pos, node, rulename, recdepth + 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth)
|
||||||
|
if (MESECONS_GLOBALSTEP) then -- do not resume if we don't use globalstep - that would cause an endless loop
|
||||||
|
mesecon:turnoff(pos, rulename, recdepth)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
function mesecon:connected_to_receptor(pos, rulename)
|
function mesecon:connected_to_receptor(pos, rulename)
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
|
@ -2,4 +2,31 @@ minetest.swap_node = minetest.swap_node or function(pos, node)
|
|||||||
local data = minetest.get_meta(pos):to_table()
|
local data = minetest.get_meta(pos):to_table()
|
||||||
minetest.add_node(pos, node)
|
minetest.add_node(pos, node)
|
||||||
minetest.get_meta(pos):from_table(data)
|
minetest.get_meta(pos):from_table(data)
|
||||||
end
|
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"}
|
||||||
|
|
||||||
|
function legacy_update_ports(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
L = {
|
||||||
|
a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a),
|
||||||
|
mesecon:invertRule(rules.a)) and
|
||||||
|
mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos),
|
||||||
|
b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b),
|
||||||
|
mesecon:invertRule(rules.b)) and
|
||||||
|
mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos),
|
||||||
|
c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c),
|
||||||
|
mesecon:invertRule(rules.c)) and
|
||||||
|
mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos),
|
||||||
|
d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d),
|
||||||
|
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
|
||||||
|
meta:set_int("real_portstates", n)
|
||||||
|
return L
|
||||||
|
end
|
||||||
|
@ -6,19 +6,19 @@ mesecon.on_placenode = function (pos, node)
|
|||||||
mesecon:turnon (pos)
|
mesecon:turnon (pos)
|
||||||
--mesecon:receptor_on (pos, mesecon:conductor_get_rules(node))
|
--mesecon:receptor_on (pos, mesecon:conductor_get_rules(node))
|
||||||
else
|
else
|
||||||
mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on")
|
mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1)
|
||||||
mesecon:activate(pos, node)
|
mesecon:activate(pos, node, nil, 1)
|
||||||
end
|
end
|
||||||
elseif mesecon:is_conductor_on(node) then
|
elseif mesecon:is_conductor_on(node) then
|
||||||
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)})
|
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)})
|
||||||
elseif mesecon:is_effector_on (node.name) then
|
elseif mesecon:is_effector_on (node.name) then
|
||||||
mesecon:deactivate(pos, node)
|
mesecon:deactivate(pos, node, nil, 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.on_dignode = function (pos, node)
|
mesecon.on_dignode = function (pos, node)
|
||||||
if mesecon:is_conductor_on(node) then
|
if mesecon:is_conductor_on(node) then
|
||||||
mesecon:receptor_off_i(pos, mesecon:conductor_get_rules(node))
|
mesecon:receptor_off(pos, mesecon:conductor_get_rules(node))
|
||||||
elseif mesecon:is_receptor_on(node.name) then
|
elseif mesecon:is_receptor_on(node.name) then
|
||||||
mesecon:receptor_off(pos, mesecon:receptor_get_rules(node))
|
mesecon:receptor_off(pos, mesecon:receptor_get_rules(node))
|
||||||
end
|
end
|
||||||
|
@ -7,3 +7,5 @@ PISTON_MAXIMUM_PUSH = 15
|
|||||||
MOVESTONE_MAXIMUM_PUSH = 100
|
MOVESTONE_MAXIMUM_PUSH = 100
|
||||||
MESECONS_GLOBALSTEP = true -- true = receptors/effectors won't be updated
|
MESECONS_GLOBALSTEP = true -- true = receptors/effectors won't be updated
|
||||||
-- until next globalstep, decreases server load
|
-- until next globalstep, decreases server load
|
||||||
|
MESECONS_RESUMETIME = 4 -- time to wait when starting the server before
|
||||||
|
-- processing the ActionQueue, don't set this too low
|
||||||
|
@ -169,6 +169,7 @@ function mesecon:cmpSpecial(r1, r2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:tablecopy(table) -- deep table copy
|
function mesecon:tablecopy(table) -- deep table copy
|
||||||
|
if type(table) ~= "table" then return table end -- no need to copy
|
||||||
local newtable = {}
|
local newtable = {}
|
||||||
|
|
||||||
for idx, item in pairs(table) do
|
for idx, item in pairs(table) do
|
||||||
@ -181,3 +182,14 @@ function mesecon:tablecopy(table) -- deep table copy
|
|||||||
|
|
||||||
return newtable
|
return newtable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mesecon:cmpAny(t1, t2)
|
||||||
|
if type(t1) ~= type(t2) then return false end
|
||||||
|
if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end
|
||||||
|
|
||||||
|
for i, e in pairs(t1) do
|
||||||
|
if not mesecon:cmpAny(e, t2[i]) then return false end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
@ -17,28 +17,18 @@ end
|
|||||||
|
|
||||||
-- Functions that are called after the delay time
|
-- Functions that are called after the delay time
|
||||||
|
|
||||||
local delayer_turnon = function(params)
|
|
||||||
local rules = delayer_get_output_rules(params.node)
|
|
||||||
mesecon:receptor_on(params.pos, rules)
|
|
||||||
end
|
|
||||||
|
|
||||||
local delayer_turnoff = function(params)
|
|
||||||
local rules = delayer_get_output_rules(params.node)
|
|
||||||
mesecon:receptor_off(params.pos, rules)
|
|
||||||
end
|
|
||||||
|
|
||||||
local delayer_activate = function(pos, node)
|
local delayer_activate = function(pos, node)
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
local time = def.delayer_time
|
local time = def.delayer_time
|
||||||
minetest.swap_node(pos, {name = def.delayer_onstate, param2=node.param2})
|
minetest.swap_node(pos, {name = def.delayer_onstate, param2=node.param2})
|
||||||
minetest.after(time, delayer_turnon , {pos = pos, node = node})
|
mesecon.queue:add_action(pos, "receptor_on", {rules=delayer_get_output_rules(node)}, time, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
local delayer_deactivate = function(pos, node)
|
local delayer_deactivate = function(pos, node)
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
local time = def.delayer_time
|
local time = def.delayer_time
|
||||||
minetest.swap_node(pos, {name = def.delayer_offstate, param2=node.param2})
|
minetest.swap_node(pos, {name = def.delayer_offstate, param2=node.param2})
|
||||||
minetest.after(time, delayer_turnoff, {pos = pos, node = node})
|
mesecon.queue:add_action(pos, "receptor_off", {rules=delayer_get_output_rules(node)}, time, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Register the 2 (states) x 4 (delay times) delayers
|
-- Register the 2 (states) x 4 (delay times) delayers
|
||||||
|
@ -23,7 +23,8 @@ function gate_get_input_rules_twoinputs(node)
|
|||||||
return gate_rotate_rules(node)
|
return gate_rotate_rules(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
function update_gate(pos)
|
function update_gate(pos, node, rulename, newstate)
|
||||||
|
yc_update_real_portstates(pos, node, rulename, newstate)
|
||||||
gate = get_gate(pos)
|
gate = get_gate(pos)
|
||||||
L = rotate_ports(
|
L = rotate_ports(
|
||||||
yc_get_real_portstates(pos),
|
yc_get_real_portstates(pos),
|
||||||
|
@ -31,18 +31,46 @@ rules.d = {x = 0, y = 0, z = -1, name="D"}
|
|||||||
------------------
|
------------------
|
||||||
-- These helpers are required to set the portstates of the luacontroller
|
-- These helpers are required to set the portstates of the luacontroller
|
||||||
|
|
||||||
|
function lc_update_real_portstates(pos, rulename, newstate)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
if rulename == 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)
|
||||||
|
n = meta:get_int("real_portstates") - 1
|
||||||
|
end
|
||||||
|
local L = {}
|
||||||
|
for i = 1, 4 do
|
||||||
|
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]
|
||||||
|
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
|
||||||
|
end
|
||||||
|
meta:set_int("real_portstates", 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 get_real_portstates = function(pos) -- determine if ports are powered (by itself or from outside)
|
||||||
ports = {
|
local meta = minetest.get_meta(pos)
|
||||||
a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a), mesecon:invertRule(rules.a))
|
local L = {}
|
||||||
and mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos),
|
local n = meta:get_int("real_portstates") - 1
|
||||||
b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b), mesecon:invertRule(rules.b))
|
if n < 0 then
|
||||||
and mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos),
|
return legacy_update_ports(pos)
|
||||||
c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c), mesecon:invertRule(rules.c))
|
end
|
||||||
and mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos),
|
for _, index in ipairs({"a", "b", "c", "d"}) do
|
||||||
d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d), mesecon:invertRule(rules.d))
|
L[index] = ((n%2) == 1)
|
||||||
and mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos),
|
n = math.floor(n/2)
|
||||||
}
|
end
|
||||||
return ports
|
return L
|
||||||
end
|
end
|
||||||
|
|
||||||
local merge_portstates = function (ports, vports)
|
local merge_portstates = function (ports, vports)
|
||||||
@ -457,6 +485,7 @@ local mesecons = {
|
|||||||
{
|
{
|
||||||
rules = input_rules[cid],
|
rules = input_rules[cid],
|
||||||
action_change = function (pos, _, rulename, newstate)
|
action_change = function (pos, _, rulename, newstate)
|
||||||
|
lc_update_real_portstates(pos, rulename, newstate)
|
||||||
lc_update(pos, {type=newstate, pin=rulename})
|
lc_update(pos, {type=newstate, pin=rulename})
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,8 @@ mesecon:add_rules(nodename, rules)
|
|||||||
local mesecons = {effector =
|
local mesecons = {effector =
|
||||||
{
|
{
|
||||||
rules = input_rules,
|
rules = input_rules,
|
||||||
action_change = function (pos, node, rulename)
|
action_change = function (pos, node, rulename, newstate)
|
||||||
|
yc_update_real_portstates(pos, node, rulename, newstate)
|
||||||
update_yc(pos)
|
update_yc(pos)
|
||||||
end
|
end
|
||||||
}}
|
}}
|
||||||
@ -633,25 +634,45 @@ function yc_set_portstate(port, state, L)
|
|||||||
return L
|
return L
|
||||||
end
|
end
|
||||||
|
|
||||||
function yc_get_real_portstates(pos) -- port powered or not (by itself or from outside)?
|
function yc_update_real_portstates(pos, node, rulename, newstate)
|
||||||
rulesA = mesecon:get_rules("mesecons_microcontroller:microcontroller0001")
|
local meta = minetest.get_meta(pos)
|
||||||
rulesB = mesecon:get_rules("mesecons_microcontroller:microcontroller0010")
|
if rulename == nil then
|
||||||
rulesC = mesecon:get_rules("mesecons_microcontroller:microcontroller0100")
|
meta:set_int("real_portstates", 1)
|
||||||
rulesD = mesecon:get_rules("mesecons_microcontroller:microcontroller1000")
|
return
|
||||||
L = {
|
end
|
||||||
a = mesecon:is_power_on(mesecon:addPosRule(pos, rulesA[1]),
|
local n = meta:get_int("real_portstates") - 1
|
||||||
mesecon:invertRule(rulesA[1])) and
|
if n < 0 then
|
||||||
mesecon:rules_link(mesecon:addPosRule(pos, rulesA[1]), pos),
|
legacy_update_ports(pos)
|
||||||
b = mesecon:is_power_on(mesecon:addPosRule(pos, rulesB[1]),
|
n = meta:get_int("real_portstates") - 1
|
||||||
mesecon:invertRule(rulesB[1])) and
|
end
|
||||||
mesecon:rules_link(mesecon:addPosRule(pos, rulesB[1]), pos),
|
local L = {}
|
||||||
c = mesecon:is_power_on(mesecon:addPosRule(pos, rulesC[1]),
|
for i = 1, 4 do
|
||||||
mesecon:invertRule(rulesC[1])) and
|
L[i] = n%2
|
||||||
mesecon:rules_link(mesecon:addPosRule(pos, rulesC[1]), pos),
|
n = math.floor(n/2)
|
||||||
d = mesecon:is_power_on(mesecon:addPosRule(pos, rulesD[1]),
|
end
|
||||||
mesecon:invertRule(rulesD[1])) and
|
if rulename.x == nil then
|
||||||
mesecon:rules_link(mesecon:addPosRule(pos, rulesD[1]), pos),
|
for _, rname in ipairs(rulename) do
|
||||||
}
|
local port = ({4, 1, nil, 3, 2})[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
|
||||||
|
end
|
||||||
|
meta:set_int("real_portstates", 1 + L[1] + 2*L[2] + 4*L[3] + 8*L[4])
|
||||||
|
end
|
||||||
|
|
||||||
|
function yc_get_real_portstates(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)
|
||||||
|
end
|
||||||
|
for _, index in ipairs({"a", "b", "c", "d"}) do
|
||||||
|
L[index] = ((n%2) == 1)
|
||||||
|
n = math.floor(n/2)
|
||||||
|
end
|
||||||
return L
|
return L
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user