LuaATC: add interrupt_safe() and clear_interrupts(), fix queue mainloop

This commit is contained in:
orwell96 2021-02-17 19:45:52 +01:00
parent 1e4156d0a4
commit 04c78373f1
3 changed files with 56 additions and 6 deletions

View File

@ -20,6 +20,13 @@ Create environment with the given name. To be able to do anything, you first nee
- `/env_setup <env_name>`: - `/env_setup <env_name>`:
Invoke the form to edit the environment's initialization code. For more information, see the section on active components. You can also delete an environment from here. Invoke the form to edit the environment's initialization code. For more information, see the section on active components. You can also delete an environment from here.
- `/env_subscribe <env_name>`, `/env_unsubscribe <env_name>`:
Subscribe or unsubscribe from log/error messages originating from this environment
- `/env_subscriptions [env_name]`:
List your subscriptions or players subscribed to an environment.
## Functions and variables ## Functions and variables
### General Functions and Variables ### General Functions and Variables
The following standard Lua libraries are available: The following standard Lua libraries are available:
@ -71,11 +78,17 @@ Set the state of the passive component at position `pos`.
Checks whether there is a passive component at the position pos (and/or whether a passive component with this name exists) Checks whether there is a passive component at the position pos (and/or whether a passive component with this name exists)
- `interrupt(time, message)` - `interrupt(time, message)`
Cause LuaAutomation to trigger an `int` event on this component after the given time in seconds with the specified `message` field. `message` can be of any Lua data type. *Not available in init code.* Cause LuaAutomation to trigger an `int` event on this component after the given time in seconds with the specified `message` field. `message` can be of any Lua data type. Returns true. *Not available in init code.*
- `interrupt_safe(time, message)`
Like `interrupt()`, but does not add an interrupt and returns false when an interrupt (of any type) is already present for this component. Returns true when interrupt was successfully added.
- `interrupt_pos(pos, message)` - `interrupt_pos(pos, message)`
Immediately trigger an `ext_int` event on the active component at position pos. `message` is like in interrupt(). Use with care, or better **_don't use_**! Incorrect use can result in **_expotential growth of interrupts_**. Immediately trigger an `ext_int` event on the active component at position pos. `message` is like in interrupt(). Use with care, or better **_don't use_**! Incorrect use can result in **_expotential growth of interrupts_**.
- `clear_interrupts()`
Removes any pending interrupts of this node.
- `digiline_send(channel, message)` - `digiline_send(channel, message)`
Make this active component send a digiline message on the specified channel. Make this active component send a digiline message on the specified channel.
Not available in init code. Not available in init code.

View File

@ -122,6 +122,18 @@ function ac.run_in_env(pos, evtdata, customfct_p)
assert(t >= 0) assert(t >= 0)
atlatc.interrupt.add(t, pos, {type="int", int=true, message=imesg, msg=imesg}) --Compatiblity "message" field. atlatc.interrupt.add(t, pos, {type="int", int=true, message=imesg, msg=imesg}) --Compatiblity "message" field.
end end
customfct.interrupt_safe=function(t, imesg)
assertt(t, "number")
assert(t >= 0)
if atlatc.interrupt.has_at_pos(pos) then
return false
end
atlatc.interrupt.add(t, pos, {type="int", int=true, message=imesg, msg=imesg}) --Compatiblity "message" field.
return true
end
customfct.clear_interrupts=function()
atlatc.interrupt.clear_ints_at_pos(pos)
end
-- add digiline_send function, if digiline is loaded -- add digiline_send function, if digiline is loaded
if minetest.global_exists("digiline") then if minetest.global_exists("digiline") then
customfct.digiline_send=function(channel, msg) customfct.digiline_send=function(channel, msg)

View File

@ -16,6 +16,30 @@ function iq.save()
return {queue = queue, timer=timer} return {queue = queue, timer=timer}
end end
function iq.has_at_pos(pos)
for i=1,#queue do
local qe=queue[i]
if vector.equals(pos, qe.p) then
return true
end
end
return false
end
function iq.clear_ints_at_pos(pos)
local i=1
while i<=#queue do
local qe=queue[i]
if not qe then
table.remove(queue, i)
elseif vector.equals(pos, qe.p) and (qe.e.int or qe.e.ext_int) then
table.remove(queue, i)
else
i=i+1
end
end
end
function iq.add(t, pos, evtdata) function iq.add(t, pos, evtdata)
queue[#queue+1]={t=t+timer, p=pos, e=evtdata} queue[#queue+1]={t=t+timer, p=pos, e=evtdata}
run=true run=true
@ -23,13 +47,14 @@ end
function iq.mainloop(dtime) function iq.mainloop(dtime)
timer=timer + math.min(dtime, 0.2) timer=timer + math.min(dtime, 0.2)
for i=1,#queue do local i=1
while i<=#queue do
local qe=queue[i] local qe=queue[i]
if not qe then if not qe then
table.remove(queue, i) table.remove(queue, i)
i=i-1
elseif timer>qe.t then elseif timer>qe.t then
local pos, evtdata=queue[i].p, queue[i].e table.remove(queue, i)
local pos, evtdata=qe.p, qe.e
local node=advtrains.ndb.get_node(pos) local node=advtrains.ndb.get_node(pos)
local ndef=minetest.registered_nodes[node.name] local ndef=minetest.registered_nodes[node.name]
if ndef and ndef.luaautomation and ndef.luaautomation.fire_event then if ndef and ndef.luaautomation and ndef.luaautomation.fire_event then
@ -37,8 +62,8 @@ function iq.mainloop(dtime)
else else
atwarn("[atlatc][interrupt] Couldn't run event",evtdata.type,"on",pos,", something wrong with the node",node) atwarn("[atlatc][interrupt] Couldn't run event",evtdata.type,"on",pos,", something wrong with the node",node)
end end
table.remove(queue, i) else
i=i-1 i=i+1
end end
end end
end end