Module EventManagerLite
Native multi-handler events.
EventManagerLite mimics the LuaBootstrap api to allow mods to register multiple handlers to any event with only minimal code changes.
To prevent errors, EventManagerLite blocks direct access to LuaBootstrap. It's methods must instead be accessed via a ManagedLuaBootstrap object.
Module Status: Experimental 2021-08-19.
Usage:
local EventManager = require('__eradicators-library__/erlib/factorio/EventManagerLite-1')()
    
Public methods
| events | Custom event names. | 
| get_managed_script(module_name) | Creates a new ManagedLuaBootstrap instance or fetches an existing one of the same name. | 
Concepts
| EventName | The unique name of an event. | 
Factorio Behavior
| api_availability | What apis are available during on_init, on_load and on_config? | 
| boostrap_event_order | In what order do on_init, on_load and on_config happen? | 
| event_handler_order | In what order are handlers executed? | 
Examples
| Examples | 
ManagedLuaBootstrap
| ManagedLuaBootstrap | The main interface of EventManagerLite. | 
| ManagedLuaBootstrap.on_event(event_name, f, filters) | Register event handlers. | 
| ManagedLuaBootstrap.on_nth_tick(period, f) | Changed. | 
| ManagedLuaBootstrap.on_init() | Removed. | 
| ManagedLuaBootstrap.on_load(f) | Changed. | 
| ManagedLuaBootstrap.on_configuration_changed(f) | Changed. | 
| ManagedLuaBootstrap.on_config() | New: Shorthand for on_configuration_changed(f). | 
| ManagedLuaBootstrap.generate_event_name([event_name]) | Changed. | 
| ManagedLuaBootstrap.module_name | New: The name that was used to create this instance. | 
| ManagedLuaBootstrap.module_index | New: The load order index of this instance. | 
| ManagedLuaBootstrap.object_name | Changed. | 
| ManagedLuaBootstrap.events | New: Alias for EventManagerLite.events. | 
| ManagedLuaBootstrap.set_event_filter() | Removed. | 
| ManagedLuaBootstrap.get_event_filter() | Removed. | 
Commands
| dump | Dumps handler registration data to the attached terminal. | 
ExtraEvents
| HowToActivateExtraEvents | Extra events must be activated in settings stage prior to usage. | 
| on_entity_created | All-in-one entity building event. | 
| on_player_changed_chunk | Raised when the player moves or is teleported across a chunk border on the same surface, or has moved to another surface. | 
| on_user_panic | Raised when a player calls "DON'T PANIC!" in the chat. | 
	
TickedAction
| on_ticked_action | Called when an action should happen. | 
| TickedAction.enqueue(module_name, method_name, offsets[, parameter]) | Plans a future action. | 
| TickedAction.dequeue(module_name, method_name[, ticks]) | Cancels a future action before it happens. | 
Public methods
- events
 - 
    Custom event names.
 Erlibs equivalent to defines.events for modded event ids.
 This is the recommended way of sharing EventNames between mods.
This table contains all dynamically generated (event_name → event_id) mappings that are contained in the Remote.PackedInterfaceGroup
'erlib:managed-events'. Take care to use the correct load order and declare dependencies as needed.Trying to read event names that have not been defined yet is an error. It is possible, but discouraged to add event ids by writing them directly to this table. It is recommended to use generate_event_name to generate new names.
See also remotes.events.
Usage:
-- Mod_A: ManagedLuaBootstrap.generate_event_name('on_something_happend') -- Mod_X (can be Mod_A): script.on_event(events.on_something_happend, function(e) print('I just shared an event name without effort!') end) -- Mod_A: script.raise_event(events.on_something_happend, {player_index = ...}) -- Mod_X (can be Mod_A): > I just shared an event name without effort!
 - get_managed_script(module_name)
 - 
    Creates a new ManagedLuaBootstrap instance or fetches an existing one of
 the same name. 
On the first call to this function with a new module_name a unique module_index is generated. Subsequent calls share the same index.
Parameters:
- module_name string The name of your module.
 
Returns:
- 
           ManagedLuaBootstrap
         If an instance of the same name has been
 created before you will recieve a reference to, not a copy of,
 that exact same instance table.
    
 
 
Concepts
- EventName
 - 
    The unique name of an event. 
An EventName is any NaturalNumber or string that would normally be used to register an event handler with script.on_event().
That means any NaturalNumber from defines.events, any NaturalNumber number generated with script.generate_event_name(), any name string of a LuaCustomInputPrototype, or one of the literal strings
"on_load","on_config" and"on_configuration_changed". 
Factorio Behavior
- api_availability
 - 
    What apis are available during on_init, on_load and on_config?
    
Usage:
on_init : remote commands settings rcon rendering script game global[R/W] on_load : remote commands settings rcon script global[R] on_config : remote commands settings rcon rendering script game global[R/W]
 - boostrap_event_order
 - 
In what order do on_init, on_load and on_config happen?
Absurdly the engine raises on_load* before on_config, at best causing unnesscary work, at worst running it on outdated global data. There's nothing I can do about that so you have to take countermeasures yourself. Don't forget to use migrations if nessecary.
See ManagedLuaBootstrap.on_init for why EventManagerLite never raises on_init.
Base game order:
InstallMod -> StartMap : on_init - - InstallMod -> StartMap -> SaveMap -> LoadMap: - on_load - InstallMod -> StartMap -> ChangeMod -> LoadMap: - on_load* on_config StartMap -> SaveMap -> InstallMod -> LoadMap: on_init - on_configEventManagerLite order:
InstallMod -> StartMap : on_config - - InstallMod -> StartMap -> SaveMap -> LoadMap: - on_load - InstallMod -> StartMap -> UpdateMod -> LoadMap: - on_load* on_config StartMap -> SaveMap -> InstallMod -> LoadMap: on_config - on_config - event_handler_order
 - 
    In what order are handlers executed? 
When two mods or two ManagedLuaBootstrap instances each have a handler for the same event, then the events are executed in the order that they were loaded in. For ManagedLuaBootstrap this is determined by the module_index.
When multiple On_nth_tick handlers occur on the same tick then the handlers are executed in order from smallest to largest period. All on_tick handlers are always executed before any on_nth_tick handlers.
 
Examples
- Examples
 - 
    
Usage:
-- same basic syntax as script.on_event local script = EventManagerLite.get_managed_script('my-scripted-entity') script.on_event(defines.events.on_entity_damaged, function(e) game.print{'', 'Entity ', e.entity.name, ' was damaged.'} end }
-- on_config replaces on_init and on_configuration_changed local script = EventManagerLite.get_managed_script('my-scripted-entity') script.on_config(function(e) print('This is a shortcut to on_configuration_changed!') end)
 
ManagedLuaBootstrap
- ManagedLuaBootstrap
 - 
    The main interface of EventManagerLite.  Each instance can have one handler
 for every event, just like a normal factorio mod can. Differently named
 instances act like seperate mods and do not interfer with each others events.
This section documents only the changes compared to LuaBootstrap. Everything not mentioned here works exactly the same as it normally does (i.e. script.active_mods, script.generate_event_name, script.raise_event etc).
Changed: ManagedLuaBootstrap is not write-protected like real LuaBootstrap. Changes you make will be visible in all instances with the same name.
 - ManagedLuaBootstrap.on_event(event_name, f, filters)
 - 
    Register event handlers.
 (See also LuaBootstrap.on_event.)
    
Parameters:
- event_name
            EventName or table
         Changed: Accepts values of
 any type of table, not only of arrays,
 and recognizes the strings 
'on_load','on_config'and'on_configuration_changed'. - f function or nil Unchanged.
 - filters nil Removed. Because filtering would need to be done on the lua side there would be no performance benefit.
 
Returns:
Usage:
local my_handler = script.on_event(defines.events, function(e) end)
 - event_name
            EventName or table
         Changed: Accepts values of
 any type of table, not only of arrays,
 and recognizes the strings 
 - ManagedLuaBootstrap.on_nth_tick(period, f)
 - 
    Changed.  To prevent lag spikes when several modules with handlers
 for the same period all execute on the same tick, each handler
 is assigned a random offset. The offset is deterministic and
 always the same for a given combination of module_name and period.
The offset is included in the event table when the handler is called.
For example:f{nth_tick = 30, offset = 9, tick = 39}.The offset always fullfills the condition:
(tick % nth_tick) == offset.Parameters:
- period NaturalNumber Unchanged.
 - f function or nil Unchanged.
 
Returns:
 - ManagedLuaBootstrap.on_init()
 - 
    Removed. 
Because factorio only raises on_init once per mod this is not reliable for adding new modules to an existing savegame. To prevent any confusion it is completely disabled. Use on_configuration_changed instead.
 - ManagedLuaBootstrap.on_load(f)
 - 
    Changed.
    
Parameters:
Returns:
 - ManagedLuaBootstrap.on_configuration_changed(f)
 - 
    Changed.  Because on_init is not reliable, on_configuration_changed handlers
 must also handle on_init in an agnostic manner.
If the handler is raised during on_init it will be raised without parameters. Warning: Do not try to outsmart yourself by using this to "detect" on_init. There is no guarantee that this will ever happen at all. It's best if you just store a private "is_initialized" flag in your modules global data if you need to do heavy lifting in on_init.
See also EventManagerLite.boostrap_event_order, LuaBootstrap.on_configuration_changed
Parameters:
- f function or nil Changed: Will sometimes be raised f(nil) instead of f(ConfigurationChangedData).
 
Returns:
 - ManagedLuaBootstrap.on_config()
 - New: Shorthand for on_configuration_changed(f).
 - ManagedLuaBootstrap.generate_event_name([event_name])
 - 
    Changed.  Now supports naming events.
 If a name is given it's id is automatically published to the
 Remote.PackedInterfaceGroup called 'erlib:managed-events',
 which can easily be accessed via EventManagerLite.events.
See also LuaBootstrap.generate_event_name and remotes.events.
Parameters:
- event_name string Your custom name for the event. (optional)
 
Returns:
- 
           NaturalNumber
         The EventName
 for your event. A new EventName will only be generated on the first
 call for each 
 
event_name. Subsequent calls with the sameevent_namewill return the previously generated EventName. - ManagedLuaBootstrap.module_name
 - 
    New: The name that was used to create this instance.
 Similar to LuaBootstrap.mod_name but not the same.
Read only. (Technically you can overwrite it but that won't affect anything.)
 - ManagedLuaBootstrap.module_index
 - 
    New: The load order index of this instance.  When an event is subscribed to by
 multiple instances then the handlers will be executed in this order, starting
 from lowest going to highest.
Read only. (Technically you can overwrite it but that won't affect anything.)
See also EventManagerLite.event_handler_order.
 - ManagedLuaBootstrap.object_name
 - 
    Changed.  The name is 
"ManagedLuaBootstrap". To distinguish from the real script which is named"LuaBootstrap".Read only. (Technically you can overwrite it but that won't affect anything.)
See also Common.object_name.
 - ManagedLuaBootstrap.events
 - New: Alias for EventManagerLite.events.
 - ManagedLuaBootstrap.set_event_filter()
 - Removed. Event filters are not supported.
 - ManagedLuaBootstrap.get_event_filter()
 - Removed. Event filters are not supported.
 
Commands
- dump
 - 
    Dumps handler registration data to the attached terminal.
 This command only works when the erlib debug-mode sub-mod is active.
 Any incorrect usage is silently ignored.  
/erlib event-manager dump <mod_name> 
ExtraEvents
- HowToActivateExtraEvents
 - 
    Extra events must be activated in settings stage prior to usage. 
erlib_enable_plugin(<extra_event_name>)Usage:
-- settings.lua erlib_enable_plugin('on_entity_created') erlib_enable_plugin('on_player_changed_chunk') erlib_enable_plugin('on_ticked_action')
 - on_entity_created
 - 
    All-in-one entity building event. 
Combines the following events:
on_built_entity
on_robot_built_entity
script_raised_built
script_raised_revive
on_entity_cloned
on_trigger_created_entityFields:
- created_entity LuaEntity The entity built.
 - player_index NaturalNumber (optional)
 - robot LuaEntity The robot that did the building. (optional)
 - stack LuaItemStack The item used to do the building. (optional)
 - item LuaItemPrototype The item prototype used to build the entity. Note this won't exist in some situations (built from blueprint, undo, etc). (optional)
 - tags Tags The tags associated with this entity. (optional)
 - clone_source LuaEntity The entity that this entity was cloned from. (optional)
 - trigger_source LuaEntity The entity with a trigger prototype (such as capsules) that created this entity. (optional)
 
 - on_player_changed_chunk
 - 
    Raised when the player moves or is teleported across a chunk border on
 the same surface, or has moved to another surface.  After a surface
 was deleted this is called for all players regardless of if they were
 actually on that surface.
Abstracts:
on_player_changed_position
on_player_changed_surfaceFields:
- player_index uint
 - surface_index uint or nil If the player changed surfaces then this is the old surfaces index.
 - old_chunk ChunkPositionAndArea
 - new_chunk ChunkPositionAndArea
 
 - on_user_panic
 - 
    Raised when a player calls 
"DON'T PANIC!"in the chat. You should trigger some generic sanity checking and garbage collection of your mods internal state now.Commands typed on the server console and commands raised by mods do not have a
player_index, making them indistinguishable from each other, so they are filtered out and do not raise anything.If the player is an admin or the game is Singleplayer then an additional event
on_admin_panicis raised.See also: on_console_chat
Fields:
- player_index uint (not optional)
 - message string
 - calming_words string The key for the localised string you should print when you're done.
 
Usage:
script.on_event(EventManager.events.on_user_panic, function(e) dostuff() Player.get_event_player(e).print{e.calming_words, 'name-of-your-content'} end)
 
TickedAction
Usage:
-- settings.lua erlib_enable_plugin('on_ticked_action') -- control.lua local Action = Remote.get_interface('erlib:on_ticked_action') local my_actions = { doit = function(name) print(name .. ' did it !') end } script.on_event(EventManagerLite.events.on_ticked_action, function(e) if e.module_name == 'my-module' then if e.method_name == 'doit' then my_actions.doit(e.parameter.name) end end end) script.on_event(defines.events.on_something_happend, function(e) Action.enqueue('my-module', 'doit', 60*5, {name = 'The gardener'}) end) -- 5 seconds later > The gardener did it!
- on_ticked_action
 - 
    Called when an action should happen.  Events with the same tick are
 raised in the order they were enqueued in.
See also EventManagerLite.events
Fields:
 - TickedAction.enqueue(module_name, method_name, offsets[, parameter])
 - 
    Plans a future action.
    
Parameters:
- module_name string A name to identify your event later.
 - method_name string A name to identify your event later.
 - offsets NaturalNumber or DenseArray How many ticks from now you want the action to happen. You can plan several ticks at once.
 - parameter string, boolean, table or number You can store data here to retrieve it in the event later. The data must survive a remote call, global Savedata save/load cycles and script.raise_event, so it's best to keep it simple. (optional)
 
 - TickedAction.dequeue(module_name, method_name[, ticks])
 - 
    Cancels a future action before it happens.
    
Parameters:
- module_name string
 - method_name string
 - ticks NaturalNumber or DenseArray You can either unplan all actions with matching names, or only actions that were planned for the given ticks. (optional)