summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesecons/actionqueue.lua119
-rw-r--r--mesecons/init.lua82
-rw-r--r--mesecons/internal.lua229
-rw-r--r--mesecons/services.lua8
-rw-r--r--mesecons/util.lua12
-rw-r--r--mesecons_commandblock/depends.txt1
-rw-r--r--mesecons_commandblock/init.lua210
-rw-r--r--mesecons_delayer/init.lua14
8 files changed, 275 insertions, 400 deletions
diff --git a/mesecons/actionqueue.lua b/mesecons/actionqueue.lua
new file mode 100644
index 0000000..41a587c
--- /dev/null
+++ b/mesecons/actionqueue.lua
@@ -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 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 < 5) then return end -- don't even try if server has not been running for 2 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)
diff --git a/mesecons/init.lua b/mesecons/init.lua
index 640af4d..f528dfd 100644
--- a/mesecons/init.lua
+++ b/mesecons/init.lua
@@ -42,37 +42,8 @@
-- PUBLIC VARIABLES
mesecon={} -- contains all functions and all global variables
-mesecon.actions_on={} -- Saves registered function callbacks for mesecon on | DEPRECATED
-mesecon.actions_off={} -- Saves registered function callbacks for mesecon off | DEPRECATED
-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)
+mesecon.queue={} -- contains the ActionQueue
+mesecon.queue.funcs={} -- contains all ActionQueue functions
-- Settings
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
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
-- This is the most important file
-- it handles signal transmission and basically everything else
@@ -101,9 +76,20 @@ dofile(minetest.get_modpath("mesecons").."/legacy.lua");
-- API
-- 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
+ -- if area (any of the rule targets) 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.get_node_or_nil(np) == nil then
+ mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, 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)
@@ -111,19 +97,24 @@ function mesecon:receptor_on_i(pos, rules)
mesecon:turnon(np, rulename)
end
end
-end
+end)
function mesecon:receptor_on(pos, rules)
- if MESECONS_GLOBALSTEP then
- 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
+ mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
end
-function mesecon:receptor_off_i(pos, rules)
+mesecon.queue:add_function("receptor_off", function (pos, rules)
rules = rules or mesecon.rules.default
+
+ -- if area (any of the rule targets) 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 minetest.get_node_or_nil(np) == nil then
+ mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
+ return
+ end
+ end
+
for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = mesecon:addPosRule(pos, rule)
local rulenames = mesecon:rules_link_rule_all(pos, rule)
@@ -131,19 +122,14 @@ function mesecon:receptor_off_i(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, 2)
end
end
end
-end
+end)
function mesecon:receptor_off(pos, rules)
- if MESECONS_GLOBALSTEP then
- 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
+ mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
end
diff --git a/mesecons/internal.lua b/mesecons/internal.lua
index cb77f5d..32a28b2 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
@@ -177,121 +177,76 @@ function mesecon:effector_get_rules(node)
return mesecon.rules.default
end
---Signals
+-- #######################
+-- # Signals (effectors) #
+-- #######################
-function mesecon:activate(pos, node, rulename)
- if MESECONS_GLOBALSTEP then
- if rulename == nil then
- for _,rule in ipairs(mesecon:effector_get_rules(node)) do
- mesecon:activate(pos, node, rule)
- end
- return
- 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
+-- Activation:
+mesecon.queue:add_function("activate", function (pos, rulename)
+ node = minetest.get_node(pos)
+ effector = mesecon:get_effector(node.name)
-function mesecon:deactivate(pos, node, rulename)
- if MESECONS_GLOBALSTEP then
- if rulename == nil then
- for _,rule in ipairs(mesecon:effector_get_rules(node)) do
- mesecon:deactivate(pos, node, rule)
- end
- return
- 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
+ if effector and effector.action_on then
+ effector.action_on(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
- 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)
+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, recdepth + 1)
end
+ return
end
+ mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / recdepth)
end
-function execute_actions(dtime)
- local nactions = mesecon.to_update
- mesecon.to_update = {}
- for _,i in ipairs(nactions) do
- node = minetest.get_node(i.pos)
- if node.name=="ignore" then
- add_action(i.pos, i.action, i.rname)
- else
- 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
+
+-- Deactivation
+mesecon.queue:add_function("deactivate", function (pos, rulename)
+ node = minetest.get_node(pos)
+ effector = mesecon:get_effector(node.name)
+
+ if effector and effector.action_off then
+ effector.action_off(pos, node, rulename)
end
- local nactions = mesecon.r_to_update
- mesecon.r_to_update = {}
- for _,i in ipairs(nactions) do
- if i.action == "on" then
- mesecon:receptor_on_i(i.pos, i.rules)
- else
- mesecon:receptor_off_i(i.pos,i.rules)
+end)
+
+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, recdepth + 1)
end
+ return
end
+ mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / recdepth)
end
-minetest.register_globalstep(execute_actions)
-function add_action(pos, action, rname)
- for _,i in ipairs(mesecon.to_update) do
- 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
- if (i.action == "on" and action == "on") or (i.action == "off" and action == "off") then
- --nothing
- elseif i.action == "coff" and action == "on" then i.action = "on"
- elseif i.action == "con" and action == "off" then i.action = "off"
- 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
+-- Change
+mesecon.queue:add_function("change", function (pos, rulename, changetype)
+ node = minetest.get_node(pos)
+ effector = mesecon:get_effector(node.name)
+
+ if effector and effector.action_change then
+ effector.action_change(pos, node, rulename, changetype)
+ end
+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.to_update[#mesecon.to_update+1] = {pos = pos, action = action, rname = rname}
+
+ mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / recdepth)
end
---Rules
+-- #########
+-- # Rules # "Database" for rulenames
+-- #########
function mesecon:add_rules(name, rules)
mesecon.rules[name] = rules
@@ -410,8 +365,15 @@ 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(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
local rules = mesecon:conductor_get_rules(node)
@@ -419,7 +381,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
@@ -429,54 +391,71 @@ function mesecon:turnon(pos, rulename)
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
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
- mesecon:turnon(np, rulename)
+ for _, rulename in ipairs(rulenames) do
+ mesecon:turnon(np, rulename, recdepth + 1)
+ end
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)
+mesecon.queue:add_function("turnon", function (pos, rulename, recdepth)
+ mesecon:turnon(pos, rulename, recdepth)
+end)
+
+function mesecon:turnoff(pos, rulename, recdepth)
+ recdepth = recdepth or 2
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
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
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
- mesecon:turnoff(np, rulename)
+ for _, rulename in ipairs(rulenames) do
+ mesecon:turnoff(np, rulename, recdepth + 1)
+ end
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
+mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth)
+ mesecon:turnoff(pos, rulename, recdepth)
+end)
+
function mesecon:connected_to_receptor(pos, rulename)
local node = minetest.get_node(pos)
diff --git a/mesecons/services.lua b/mesecons/services.lua
index 9d192ae..de0c8b6 100644
--- a/mesecons/services.lua
+++ b/mesecons/services.lua
@@ -6,19 +6,19 @@ 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
mesecon.on_dignode = function (pos, node)
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
mesecon:receptor_off(pos, mesecon:receptor_get_rules(node))
end
diff --git a/mesecons/util.lua b/mesecons/util.lua
index b3ca7a0..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
@@ -181,3 +182,14 @@ function mesecon:tablecopy(table) -- deep table copy
return newtable
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
diff --git a/mesecons_commandblock/depends.txt b/mesecons_commandblock/depends.txt
deleted file mode 100644
index acaa924..0000000
--- a/mesecons_commandblock/depends.txt
+++ /dev/null
@@ -1 +0,0 @@
-mesecons
diff --git a/mesecons_commandblock/init.lua b/mesecons_commandblock/init.lua
deleted file mode 100644
index af7034d..0000000
--- a/mesecons_commandblock/init.lua
+++ /dev/null
@@ -1,210 +0,0 @@
-minetest.register_chatcommand("say", {
- params = "<text>",
- description = "Say <text> as the server",
- privs = {server=true},
- func = function(name, param)
- minetest.chat_send_all(name .. ": " .. param)
- end
-})
-
-minetest.register_chatcommand("tell", {
- params = "<name> <text>",
- description = "Say <text> to <name> privately",
- func = function(name, param)
- local found, _, target, message = param:find("^([^%s]+)%s+(.*)$")
- if found == nil then
- minetest.chat_send_player(name, "Invalid usage: " .. param)
- return
- end
- if not minetest.get_player_by_name(target) then
- minetest.chat_send_player(name, "Invalid target: " .. target)
- end
- minetest.chat_send_player(target, name .. " whispers: " .. message, false)
- end
-})
-
-minetest.register_chatcommand("tellme", {
- params = "<text>",
- description = "Say <text> to yourself",
- func = function(name, param)
- minetest.chat_send_player(name, param, false)
- end
-})
-
-minetest.register_chatcommand("hp", {
- params = "<name> <value>",
- description = "Set health of <name> to <value> hitpoints",
- privs = {ban=true},
- func = function(name, param)
- local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$")
- if found == nil then
- minetest.chat_send_player(name, "Invalid usage: " .. param)
- return
- end
- local player = minetest.get_player_by_name(target)
- if player then
- player:set_hp(value)
- else
- minetest.chat_send_player(name, "Invalid target: " .. target)
- end
- end
-})
-
-local initialize_data = function(meta, player, command, param)
- meta:set_string("formspec",
- "invsize[9,6;]" ..
- "field[1,1;7.5,1;player;Player;" .. player .. "]" ..
- "button[1.3,2;2,1;nearest;Nearest]" ..
- "button[3.3,2;2,1;farthest;Farthest]" ..
- "button[5.3,2;2,1;random;Random]" ..
- "field[1,4;2,1;command;Command;" .. command .. "]" ..
- "field[3,4;5.5,1;param;Parameter;" .. param .. "]" ..
- "button_exit[3.3,5;2,1;submit;Submit]")
- local owner = meta:get_string("owner")
- if owner == "" then
- owner = "not owned"
- else
- owner = "owned by " .. owner
- end
- meta:set_string("infotext", "Command Block\n" ..
- "(" .. owner .. ")\n" ..
- "Command: /" .. command .. " " .. param)
-end
-
-local construct = function(pos)
- local meta = minetest.get_meta(pos)
-
- meta:set_string("player", "@nearest")
- meta:set_string("command", "time")
- meta:set_string("param", "7000")
-
- meta:set_string("owner", "")
-
- initialize_data(meta, "@nearest", "time", "7000")
-end
-
-local after_place = function(pos, placer)
- if placer then
- local meta = minetest.get_meta(pos)
- meta:set_string("owner", placer:get_player_name())
- initialize_data(meta, "@nearest", "time", "7000")
- end
-end
-
-local receive_fields = function(pos, formname, fields, sender)
- if fields.quit then
- return
- end
- local meta = minetest.get_meta(pos)
- if fields.nearest then
- initialize_data(meta, "@nearest", fields.command, fields.param)
- elseif fields.farthest then
- initialize_data(meta, "@farthest", fields.command, fields.param)
- elseif fields.random then
- initialize_data(meta, "@random", fields.command, fields.param)
- else --fields.submit or pressed enter
- meta:set_string("player", fields.player)
- meta:set_string("command", fields.command)
- meta:set_string("param", fields.param)
-
- initialize_data(meta, fields.player, fields.command, fields.param)
- end
-end
-
-local resolve_player = function(name, pos)
- local get_distance = function(pos1, pos2)
- return math.sqrt((pos1.x - pos2.x) ^ 2 + (pos1.y - pos2.y) ^ 2 + (pos1.z - pos2.z) ^ 2)
- end
-
- if name == "@nearest" then
- local min_distance = math.huge
- for index, player in ipairs(minetest.get_connected_players()) do
- local distance = get_distance(pos, player:getpos())
- if distance < min_distance then
- min_distance = distance
- name = player:get_player_name()
- end
- end
- elseif name == "@farthest" then
- local max_distance = -1
- for index, player in ipairs(minetest.get_connected_players()) do
- local distance = get_distance(pos, player:getpos())
- if distance > max_distance then
- max_distance = distance
- name = player:get_player_name()
- end
- end
- elseif name == "@random" then
- local players = minetest.get_connected_players()
- local player = players[math.random(#players)]
- name = player:get_player_name()
- end
- return name
-end
-
-local commandblock_action_on = function(pos, node)
- if node.name ~= "mesecons_commandblock:commandblock_off" then
- return
- end
-
- minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
-
- local meta = minetest.get_meta(pos)
- local command = minetest.chatcommands[meta:get_string("command")]
- if command == nil then
- return
- end
- local owner = meta:get_string("owner")
- if owner == "" then
- return
- end
- local has_privs, missing_privs = minetest.check_player_privs(owner, command.privs)
- if not has_privs then
- minetest.chat_send_player(owner, "You don't have permission to run this command (missing privileges: "..table.concat(missing_privs, ", ")..")")
- return
- end
- local player = resolve_player(meta:get_string("player"), pos)
- command.func(player, meta:get_string("param"))
-end
-
-local commandblock_action_off = function(pos, node)
- if node.name == "mesecons_commandblock:commandblock_on" then
- minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
- end
-end
-
-minetest.register_node("mesecons_commandblock:commandblock_off", {
- description = "Command Block",
- tiles = {"jeija_commandblock_off.png"},
- inventory_image = minetest.inventorycube("jeija_commandblock_off.png"),
- groups = {cracky=2, mesecon_effector_off=1},
- on_construct = construct,
- after_place_node = after_place,
- on_receive_fields = receive_fields,
- can_dig = function(pos,player)
- local owner = minetest.get_meta(pos):get_string("owner")
- return owner == "" or owner == player:get_player_name()
- end,
- sounds = default.node_sound_stone_defaults(),
- mesecons = {effector = {
- action_on = commandblock_action_on
- }}
-})
-
-minetest.register_node("mesecons_commandblock:commandblock_on", {
- tiles = {"jeija_commandblock_on.png"},
- groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
- light_source = 10,
- drop = "mesecons_commandblock:commandblock_off",
- on_construct = construct,
- after_place_node = after_place,
- on_receive_fields = receive_fields,
- can_dig = function(pos,player)
- local owner = minetest.get_meta(pos):get_string("owner")
- return owner == "" or owner == player:get_player_name()
- end,
- sounds = default.node_sound_stone_defaults(),
- mesecons = {effector = {
- action_off = commandblock_action_off
- }}
-})
diff --git a/mesecons_delayer/init.lua b/mesecons_delayer/init.lua
index a03737c..4ec0ebc 100644
--- a/mesecons_delayer/init.lua
+++ b/mesecons_delayer/init.lua
@@ -17,28 +17,18 @@ end
-- 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 def = minetest.registered_nodes[node.name]
local time = def.delayer_time
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
local delayer_deactivate = function(pos, node)
local def = minetest.registered_nodes[node.name]
local time = def.delayer_time
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
-- Register the 2 (states) x 4 (delay times) delayers