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_config
EventManagerLite 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_name
will 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_panic
is 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)