Page 1 of 1
About on_nth_tick(tick, f)
Posted: Mon Aug 10, 2020 9:58 pm
by kendoctor
From its description, I'm confused .
Code: Select all
on_nth_tick(tick, f)
Register a handler to run every nth tick(s). When the game is on tick 0 it will trigger all registered handlers.
on game 0 tick will trigger all registered handlers. What about this "ALL"?. on_load?on_init? or even defines.events?
defines.events should be not.
on_nth_tick 's tick parameter can not be assigned a 0 value, that proves "on tick 0" should indicate game's tick
if game 0 tick will trigger on_init, on_load..or any boostrap events
That means on game tick 1, on_init or on_load should be already invoked at least one.
As i know, in defines.events handler, you can safely access game object
How about on_nth_tick(1, handler) ?
Re: About on_nth_tick(tick, f)
Posted: Mon Aug 10, 2020 10:26 pm
by boskid
It referes only to the handlers registered by the on_nth_tick. It is possible to register at most 1 handler per each tick period so you may have different handler called every 1 tick and different every 2 ticks, but cannot have 2 handlers both called every 1 tick (in that case you have to manually distribute the event). Saying that all event handlers are called on tick 0 means only the tick handlers and this is also a shortcut way to define which ticks the handlers will be running on (ticks modulo period has to give a remainder of 0)
Re: About on_nth_tick(tick, f)
Posted: Mon Aug 10, 2020 11:24 pm
by kendoctor
boskid wrote: Mon Aug 10, 2020 10:26 pm
It referes only to the handlers registered by the on_nth_tick. It is possible to register at most 1 handler per each tick period so you may have different handler called every 1 tick and different every 2 ticks, but cannot have 2 handlers both called every 1 tick (in that case you have to manually distribute the event). Saying that all event handlers are called on tick 0 means only the tick handlers and this is also a shortcut way to define which ticks the handlers will be running on (ticks modulo period has to give a remainder of 0)
As u know, offical event register can not handle multiple handlers for same event or same tick. How, here, this statement indicates multiple handling?
Defenitely confusing.
Re: About on_nth_tick(tick, f)
Posted: Tue Aug 11, 2020 7:13 am
by darkfrei
kendoctor wrote: Mon Aug 10, 2020 11:24 pm
As u know, offical event register can not handle multiple handlers for same event or same tick. How, here, this statement indicates multiple handling?
Defenitely confusing.
Maybe as (pseudo code)
Code: Select all
on_nth_tick ()
if bool then
function_handler = function_a()
else
function_handler = function_b()
end
See also official event handler
viewtopic.php?f=34&t=84821
Re: About on_nth_tick(tick, f)
Posted: Tue Aug 11, 2020 8:37 am
by kendoctor
darkfrei wrote: Tue Aug 11, 2020 7:13 am
kendoctor wrote: Mon Aug 10, 2020 11:24 pm
As u know, offical event register can not handle multiple handlers for same event or same tick. How, here, this statement indicates multiple handling?
Defenitely confusing.
Maybe as (pseudo code)
Code: Select all
on_nth_tick ()
if bool then
function_handler = function_a()
else
function_handler = function_b()
end
See also official event handler
viewtopic.php?f=34&t=84821
thx your reply.
I already made a mutiple event handlers module.
Code: Select all
--- Event Class
-- If consider priority handlers, needs an array table to hold handlers, otherwise needs sorting before call
-- do we need coroutine to guarrantee on_loaded event which will be registered and triggered first ?
-- @classmod Event
local Event = {}
local handlers = {}
local nth_tick_handlers = {}
local loaded_handlers = {}
local loaded_event_triggered = false
local blank_call = function(e)
-- nothing to do, only trigger event == defines.events.on_tick
end
--- @todo add debug mode
function Event.callHandlersOfSameEvent(event)
if event.name == defines.events.on_tick and not loaded_event_triggered then Event.callHanldersOfLoadedEvent(event) end
for _, h in pairs(handlers[event.name]) do h(event) end
end
--- This will be called before handlers which were registered via Event.on_nth_tick(1,..)
-- loaded handlers will be only called once, when finished, will be removed at once
function Event.callHanldersOfLoadedEvent(event)
for k, h in pairs(loaded_handlers) do
h(event)
loaded_handlers[k] = nil
end
loaded_event_triggered = true
Event.remove(defines.events.on_tick, blank_call)
end
--- Call Event.on_nth_tick(...) registered handlers
function Event.callHandlersOfSameTicks(event)
-- if event.nth_tick == 1 and not loaded_event_triggered then Event.callHanldersOfLoadedEvent(event) end
for _, h in pairs(nth_tick_handlers[event.nth_tick]) do h(event) end
end
--- Add one handler to handle one event.
-- can add mulitiple handlers with same event
-- @todo priority feature with same event ?
-- if the event name does not exist, then create a key
-- handlers[event] = { handler, handler ..}
-- @tparam string|uint event
-- @tparam function handler
function Event.add(event, handler)
local sub_handlers = handlers[event]
-- if want to remove handler, should use Event.remove
if handler == nil then error("Using Event.remove to remove event handler instead of using nil handler.") end
if type(handler) ~= "function" then error("Handler should be callable.") end
if sub_handlers then
sub_handlers[handler] = handler
else
handlers[event] = { handler = handler }
script.on_event(event, Event.callHandlersOfSameEvent)
end
end
--- Same with Event.add for convenient call.
-- @tparam string|uint event
-- @tparam function handler
function Event.on(event, handler)
return Event.add(event, handler)
end
--- Set handler for one event.
-- This will remove other handlers of this event previously added
-- Filters can be applied, but only for one handler of each event
-- @tparam string|uint event
-- @tparam function handler
-- @tparam table filters
function Event.set(event, handler, filters)
-- local hf = { handler , filters }
if handler == nil then error("Using Event.remove to remove event handler instead of using nil handler.") end
Event.remove(event, nil)
if filters then
script.on_event(event, handler, filters)
else
Event.on(event, handler)
end
end
--- Remove handler(s) with event name or id.
-- if handler is nil, will remove all handlers of this event
-- @todo refactor or refine, offical script.on_event can pass array of events
-- @tparam unit|string event
-- @tparam function|nil handler
function Event.remove(event, handler)
local sub_handlers = handlers[event]
-- if handler == nil, then clear all handlers of this event
if sub_handlers then
if handler == nil then
handlers[event] = nil
else
sub_handlers[handler] = nil
-- if sub_handlers[handler] then sub_handlers[handler] = nil end
-- sub_handlers is not reference of handlers[event]
-- if sub_handlers is empty then remove this event listening
if next(sub_handlers) == nil then handlers[event] = nil end
end
end
if handlers[event] == nil then script.on_event(event, nil) end
end
--- Register handlers for initialization when game started(new game or load a save).
-- These handlers will be called once, then removed
-- Note: Registered handlers can not be removed manually.
-- @todo Queued in high priority
-- @fixme how to guarrantee handlers will be called before any other defines.events triggered?
function Event.on_loaded(handler)
if loaded_event_triggered then error("Loaded event already triggered. Not allowed to register on_loaded event in another event handler.") end
if handler == nil then error("Handler should not be nil.") end
if type(handler) ~= "function" then error("Handler should be callable.") end
if next(loaded_handlers) == nil then Event.add(defines.events.on_tick, blank_call) end
loaded_handlers[handler] = handler
end
--- Add one handler for the specific nth tick.
-- can add multiple handlers for the same nth tick
-- @tparam uint tick
-- @tparam function handler
function Event.add_nth_tick(tick, handler)
local sub_handlers = nth_tick_handlers[tick]
if handler == nil then error("Using Event.remove to remove event handler instead of using nil handler.") end
if type(handler) ~= "function" then error("Handler should be callable.") end
if sub_handlers then
sub_handlers[handler] = handler
else
nth_tick_handlers[tick] = { handler = handler }
script.on_nth_tick(tick, Event.callHandlersOfSameTicks)
end
end
--- Same with Event.add_nth_tick for convenient call.
-- if want to remove handler of the specific nth tick, using Event.remove_nth_tick
-- @tparam uint tick
-- @tparam function handler
function Event.on_nth_tick(tick, handler)
Event.add_nth_tick(tick, handler)
end
--- Remove handler or handlers for the nth tick.
-- if handler is nil, will remove all handlers of nth tick, otherwise only remove this handler
-- @tparam uint tick
-- @tparam function handler|nil
function Event.remove_nth_tick(tick, handler)
local sub_handlers = nth_tick_handlers[tick]
-- if handler == nil, then clear all handlers of this event
if sub_handlers then
if handler == nil then
nth_tick_handlers[tick] = nil
else
sub_handlers[handler] = nil
-- sub_handlers is not reference of handlers[event]
if next(sub_handlers) == nil then nth_tick_handlers[tick] = nil end
end
end
if nth_tick_handlers[tick] == nil then script.on_nth_tick(tick, nil) end
end
-- @export
return Event