Events

What are events?

Events are essentially messages broadcast to all Lua classes in the game. They are triggered when key things happen in the game. A mod can listen to game events to have behavior happen at appropriate moments.

Events have a target object and a target identifier key since all items of a certain class may want to listen on events relevant to that class, but only actually respond to events involving themselves or their children.

You can listen to events triggered from the vanilla mods, or trigger your own custom events from your code and listen to them.

Firing an event

To trigger an event, call radiant.events.trigger_async() and pass in an identifying object (usually the entity that the event concerns; if it's a general event, sometimes the service that relates to that event), the name of the event (namespaced to the mod in question) and an optional set of arguments:

  radiant.events.trigger_async(entity, 'stonehearth:admiring_fire', {})

Note that the above function triggers events asynchronously. So when you catch the event, you should confirm the worldstate. You cannot, for example, assume that objects that existed when the event was fired still exist in the world. There's also radiant.events.trigger_sync() but firing the event as async is better for performance.

Listening to an event

If a class wishes to receive an event, it registers to listen on the identifying object/string key pair, and specifies the function to call when the event is fired.

To listen on an event, call radiant.events.listen() and pass in an identifying object (should match the one that was passed into the trigger), the name of the event, and a function that should receive the arguments and be called when the event is triggered. For example:

  radiant.events.listen(entity, 'stonehearth:buff_added', function(e)
        --e has the arguments passed into the trigger
        if e.uri == uri then
           -- do stuff
        end
     end)

Or you can pass in a function that exists elsewhere in the class:

  self._attribute_listener = radiant.events.listen(entity, 'stonehearth:foo_event', self, self._on_attribute_changed)

  function ClassName:_on_attribute_changed(e)
     --do stuff
  end

Unlistening to events

Destroy an event listener when you know it's no longer relevant, to save traffic on the event pipeline and prevent errors. Refer to it by the name you used to save it.

If you no longer want to listen to an event, you can either return radiant.events.UNLISTEN in the callback function, or you can save the event and destroy it later:

  • If you want to unlisten on the event that just fired, your function should just return radiant.events.UNLISTEN instead of unlistening directly, so the events can be counted correctly in the event service. Example of unlistening from the callback:

    function ClassName:_on_attribute_changed()
       return radiant.events.UNLISTEN
    end
    
  • If an object with a listener is still listening to an event at the time it's going to be destroyed, unlisten to the event. Example here assumes that the event was saved to self._attribute_listener, like in the example of the section above:

    if self._attribute_listener then
       self._attribute_listener:destroy()
       self._attribute_listener = nil
    end
    

    This would normally be called in the destroy() function of the class.