Skip to content

How to Use LibEventHandler

Calamath edited this page May 9, 2024 · 9 revisions

Description

The main purpose of this library is to allow for a more versatile event handler than what ZOS provides through their EVENT_MANAGER. LibEventHandler expands the limitation of an event being incarcerated with only one function, to now being able to be linked to as many different functions as needed. In addition, this library allows for the firing and registering of your own local events that you create within your addon. Together, these features enable this powerful tool to allow the developer to not only be more flexible with managing events, but also to be more clean, concise, and acyclical with code.

Head onto the "Getting Started" section to learn about setup and use.

Calamath Note: I still maintain this library addon today because it was used in the LorePlay addon I maintain. Experienced authors may notice we could substitute the library features with the ZOS class library. I have annotated the API section for your reference when you consider using the library in your new project.

Getting Started

Downloading LibEventHandler

The first step to using this library is downloading it. If you haven't already, go ahead and grab it from the ESOUI page that I host it on. After downloading it, make sure that you extract it from its zip format, such that one folder named "LibEventHandler" is present, containing a few files inside it. You'll want to make sure to drag this folder into the addon folder.

Manifest File Update

It sounds complicated, but in reality this is a simple step. In order to tell ESO to load this library, you'll need to copy and paste this line into your manifest text file:

## DependsOn: LibEventHandler

And with all of this done, your setup is complete!
Move onto "Usage" to understand what to actually do with LibEventHandler.

Usage

Obtaining LibEventHandler

In order to use LibEventHandler, you'll have to first understand what it's doing.

LibEventHandler holds all the functions you want to register with any event somewhere inside of an object table. The shortest way to get started with this table is to use the following line within your code, before any attempts to register events with LibEventHandler:

local preferredEventManagerName = LibEventHandler

Now with that code, your object reference preferredEventManagerName (which from now on I'll be referring to as PEMN) can be used similarly to EVENT_MANAGER!

You're probably wondering, "That's great! But how then do I use the event handler?"
The next section, "API Methods", will finally tell you all about how to use this library's awesome abilities.

API Methods

The following methods are methods which can be used on an object reference acquired by LibStub, very similarly to how EVENT_MANAGER methods work. So without further ado, let's get started managing your events the way they should be managed:

(Note: PEMN, when seen below, should be replaced with your local variable reference.)

PEMN:RegisterForEvent(String namespace, int eventCode, func functionName)

Purpose:
Much like Zenimax's EVENT_MANAGER, RegisterForEvent will register a function to an event, such that whenever the desired event is triggered/fired, the registered function will be called with any arguments that the fired event passes to it. However, there's one powerful catch that makes this method worth using instead of the equivalent EVENT_MANAGER method:

LibEventHandler's RegisterForEvent allows for any number of functions to be registered to a given event, instead of only one like ZOS restricts. So register away, and have multiple different files be able to track a single event.

Parameters:

  • namespace: Similar usage as the EVENT_MANAGER equivalent; to which unique string/namespace will this manager associate the event? The reason for this is it makes it a lot easier for ESO to distinguish the registration of events from other namespaces and addons doing the same thing. Commonly, the unique string passed is the name of the addon.
  • eventCode: Which event are you wanting to keep track of? Whatever it is, pass in that code here. It should be a code predefined by ZOS and listed in the events page of ESOUI, i.e. EVENT_ADD_ON_LOADED.
  • functionName: Pass in the reference of a function, or an anonymous function created on the spot, here. This tells LibEventHandler what function you want to have called when the linked event passed before it, eventCode, is fired.

Calamath Note: Experienced authors may know we can register different handlers for the same event in one addon by giving different strings for namespace arguments. The original author intended to avoid unwanted conflicts and register multiple handlers more easily by this library without managing such namespace strings.

PEMN:UnregisterForEvent(String namespace, int eventCode, func functionName)

Purpose: Behaves much like ZOS's EVENT_MANAGER equivalent. If you have registered an event with LibEventHandler's RegisterForEvent function, then you may at some point want to stop having that event trigger a certain function. For example, you may register EVENT_PLAYER_ACTIVATED after your addon is done loading to call an initialize function for some UI elements. Once that event has triggered and finished initializing the UI elements in response, you might not want to have that initialization function called anymore. UnregisterForEvent allows for any passed in function to no longer be called when the linked event is fired.

What makes this great is that, unlike EVENT_MANAGER's equivalent method, you can remove a single function from being called when the event is fired, while still allowing other functions previously registered to be called.

Parameters:

  • namespace: Similar usage as the EVENT_MANAGER equivalent; to which unique string/namespace will this manager associate the event? The reason for this is it makes it a lot easier for ESO to distinguish the unregistration of events from other namespaces and addons doing the same thing. Commonly, the unique string passed is the name of the addon.
  • eventCode: From which event are you wanting to unregister a function? Whatever it is, pass in that code here. It should be a code predefined by ZOS and listed in the events page of ESOUI, i.e. EVENT_ADD_ON_LOADED. This is the event that you no longer want to trigger a specific function.
  • functionName: Pass in the reference of a function, or a function directly, here. This tells LibEventHandler what function you want to have called when eventCode is fired.

PEMN:RegisterForLocalEvent(Object eventCode, func functionName)

Purpose: This is where the true beauty of LibEventHandler shines.

This method is similar to LibEventHandler's RegisterForEvent, however RegisterForLocalEvent is going to allow you to register functions to events that have not been predefined by ESO.

For example, you may have a function OpenMyMap(), which makes the player in ESO open the in-game map. Let's say every time that happens, you want to zoom out all the way automatically. Well, ESO has not defined an event that triggers when the player opens the map! Therefore, you can create your own event (discussed below in the parameters section of this method) and listen in on when this event gets fired (firing a locally created event is discussed in a method below) using RegisterForLocalEvent.

Parameters:

  • eventCode: This eventCode is an event that you want to register for a function, however it must NOT be one that is already defined by ESO. Instead, you'll have to create your own event. This can be done by creating a local or global variable, and assigning it to something simple like an int or a string, which is why I specified it as of the type Object. Just make it simple. I personally prefer setting it to a string of the same name as the event, like so:
local EVENT_TEST_EVENT = "EVENT_TEST_EVENT"
  • functionName: Pass in the reference of a function, or an anonymous function created on the spot, here. This tells LibEventHandler what function you want to have called when eventCode is fired (discussed in the FireEvent method below).

Calamath Note: Experienced authors may know we can implement custom events by callback object. The original author intended to provide the same interface as RegisterForEvent so novice addon developers could easily use it.

PEMN:UnregisterForLocalEvent(Object eventCode, func functionName)

Purpose: Similar to LibEventHandler's UnregisterForEvent, however this method only applies for locally created events that are not defined by ESO. This method is used to cease the calling of a particular function upon the triggering of a local event.

Again, what makes this great is that you can unregister a single function from a local event as opposed to completely ceasing the listening of the event altogether.

Parameters:

  • eventCode: This eventCode is an event that you want to unregister from a function, however it must NOT be one that is already defined by ESO. Instead, you'll have to have created your own event. (Creating your own event is explained in the RegisterForLocalEvent method explanation above)
  • functionName: Pass in the reference of a function, or a function directly, here. This tells LibEventHandler what function you want to no longer be called when eventCode is fired (discussed in the FireEvent method below).

PEMN:FireEvent(Object eventCode, bool/int async, ...)

Purpose: This method is intended to allow for the triggering of your own local events!

Using a previous example, let's say you have a function which should be triggered whenever your map is opened. Well, ESO has not defined an event for the opening of the map, so you have to have created your own (Details above in RegisterForLocalEvent method explanation). However, ESO automatically deals with triggering events, and with a local event that ESO did not create, you will have to manage triggering yourself.

Calling FireEvent will allow you to have any registered functions associated with the passed event to be fired. The benefit of this system is it allows for an acyclic coding style that rids of dependencies among files.

Parameters:

  • eventCode: This eventCode is an event which must NOT be one that is already defined by ESO that you want to have triggered whenever you call this method, allowing its associated registered events to be called. Instead, you'll have to have created your own event (Details in RegisterForLocalEvent method explanation above).
  • async: In Layman's Terms, use async if you want to have an event fired separately (asynchronously) or delayed. Passing in a time in this parameter will utilize the zo_callLater() function, calling all functions registered to eventCode either 1ms later (if async is true) or after whatever time is passed into async (if async is a number). Passing in false fires the event immediately.
    The reason for this is it's the closest substitute for asynchronous performance that ZOS offers. Also, it's quite convenient to delay it should you need to respond to variable switching or any other weird circumstance.
  • ... : This is where the fun is! If you want, you can simply exclude this parameter, or you could have your registered functions receive extra information by passing in whatever you'd like here, whether it be one parameter or multiple. For example, in ESO's EVENT_PLAYER_COMBAT_STATE, both "eventCode" and "inCombat" are passed to functions that are registered with it upon firing. For your own local events, you may want to pass in similar information paralleled with "inCombat". Those data belong here. Don't forget to have your registered functions receive whatever information you may want to pass it!

Example:

local function TestMyManager(isTest, isFirstTimeCalling) 
    d(tostring(isTest)..", "..tostring(isFirstTimeCalling)) 
end

PEMN:RegisterForLocalEvent(EVENT_TEST_EVENT, TestMyManager)
PEMN:FireEvent(EVENT_TEST_EVENT, false, true, true)

--This code will immediately print "true, true"

#Conclusion And that's all there is to it! You can now register any number of functions to an event, and even make and fire your own events.
Thank you for using LibEventHandler, I can't wait to see what awesome addons utilize this library.
Happy coding!