LibChatHandler-1.0

From WIM

Jump to: navigation, search

Contents

LibChatHandler-1.0 is a lua library for the game World of Warcraft. The goal of this library is to create a common compatibility between chat addons in the game. Many developers have hardships when it comes to addons conflicting with one another such as WIM and other chat related addons such as Prat, SpamMeNot and SpamSentry.


[edit] Preface

Whats the problem?


Many addons dealing with chat require hooking Blizzard's default chat frame in order to manipulate what events are shown as well as when they are shown. For example, many spam blockers will intercept a message before it is shown to the player and runs a level check on the sender. If the sender passes the security check, the message is then delivered to the player, if not, the message is blocked or some other action is taken. When multiple addons hook the chat frame, confusion is caused and unexpected results usually occur. LibChatHandler-1.0 was created to avoid just that.


[edit] Understanding the Terminology

[edit] Model View Controller

Model View Controller or MVC is a common architecture/framework used by programmers when developing applications. Successful use of architecture isolates programmed logic from user interface, resulting in an application where it is easier to modify either the visual appearance of the application or the underlying logic rules without affecting the other. In LibChatHandler-1.0, the model represents the chat event data received by the game. The view corresponds to events getting delivered to the user interface. Finally the controller manages event delivery options and the logic rules used to manipulate the data to and from the model.


[edit] Delegate

The library itself, manages the relationships between the model, view and controllers but it doesn't process any logic itself. That's what your addon is for! Therefore we need to delegate responsibility for events to your addon. There are two ways to do this and we will explain how later in this document.


[edit] The API

[edit] Getting Started

First things first, we need to attach the LibChatHandler-1.0 to your addon. There are a couple of ways to do this depending on your preference.


  • Package the library from within your addon. You can download a copy of the library or link it through your svn and place it inside of your addon folder. Then add a reference of "LibChatHandler-1.0\lib.xml" inside of your toc file.


  • Package the library as a seperate addon. You can download a copy of the library or link it through your svn and place it along side your addon in its package to show up as a seperate addon. Your will just need to add "LibChatHandler-1.0" as a dependency inside of your addons toc file.


Which ever method you choose, you then need to reference the library from within your addon.

libCH = LibStub:GetLibrary("LibChatHandler-1.0")


[edit] Assigning a Delegate

Next, you will need to assign a delegate. As stated earlier, a delegate is responsible for providing controller functions and viewer functions if required. This will be explained in more detail later in this document.


There are two ways to assign a delegate. The choice is yours depending on how your addon was designed. What do I mean by that? Some authors develope their addons in an object oriented approach (Ace2, Ace3, LibRock & Propriety of course). Your addon and its code reside within a table object. If you don't understand this concept, then the first approach isn't for you.

  • 1. Embed the library within your addon's namespace or within an object in your addon. This will preload the required calls into your object. A list of these calls will be explained in more detail later in this document.
libCH:Embed(MyAddon)


  • 2. Create a new delegate object with all the calls needed preloaded.
delegate = libCH:NewDelegate()


For reasons none other than clarity, the object named delegate will be used when referring to future API examples. If you chose to use the Embed() method of instantiation, delegate would refer to object MyAddon.

[edit] The Delegate

A delegate inherits two calls:

[edit] RegisterChatEvent

  • RegisterChatEvent(string CHAT_EVENT, boolean PRIORITY)
    • This call registers the delegate for the requested events. Because this library is specifically for chat, non-chat related events will be ignored. If the delegate is already registered for the requested event, it will return silently. Setting the priority parameter will allow this delegate's controller to be called before others.

[edit] UnregisterChatEvent

  • UnregisterChatEvent(string CHAT_EVENT)
    • This call unregistered the delegate for the requested event. If the delegate is not registered for the specified event, it will return silently.


Example Usage

-- Register chat event
delegate:RegisterChatEvent("CHAT_MSG_WHISPER")

-- Unregister chat event
delegate:UnregisterChatEvent("CHAT_MSG_WHISPER")

[edit] Event Handling

[edit] Overview

When a delegate is registered to handle an event and the event is received from the game, LibChatHandler-1.0 looks to see if the delegate has the required functions declared, if so, it calls the functions along with the necessary parameters. These functions include:

[edit] The Controller

  • delegate:CHAT_EVENT_NAME_CONTROLLER(eventController, ...)
    • CHAT_EVENT_NAME should be replaced with the event which was registered.

Example:

function delegate:CHAT_MSG_WHISPER_CONTROLLER(eventController, msg, from, ...)
     --run logic on arguments and/or control eventController
end

Do not confuse this with the view. The event received in this function should not be finalized yet. The controller allows you to modify or take action to an event before it is delivered to Blizzard's chat frame and it's registered delegates. eventController is a complex object and will be discussed further in the next section.


[edit] The View

  • delegate:CHAT_EVENT_NAME(...)
    • CHAT_EVENT_NAME should be replaced with the event which was registered.

Example:

function delegate:CHAT_MSG_WHISPER(msg, from, ...)
     --show/run logic against delivered event
end

This event, unlike from the controller, is the final event data. All delegates have seen the event, and unless blocked have been delivered here.


[edit] eventController

LibChatHandler-1.0 takes an event and wraps it up into an object along with some useful tools for delegate controllers to use. Do not confuse eventController with the string representation of the event. Below is a representation of the eventController

[edit] GetArgs()

  • Returns unpacked list of arguments from the event. Equivalent to the (...) received by the OnEvent script handler.

Example:

local arg1, arg2, arg3, arg4, arg5 = eventController:GetArgs()


[edit] GetEvent()

  • Returns the event name as a string.

Example:

local event = eventController:GetEvent()


[edit] Block()

Block the event. Do not allow this event to be delivered.

Example:

eventController:Block()

In this example, the event is blocked and will not be delivered to any registered viewers.


[edit] BlockFromChatFrame()

Block the event from being delivered to Blizzard's chat frame, but continue to deliver the event to all registered delegates. This is useful if you want to supress messages from the chat frame, but display the event data elsewhere.

Example:

eventController:BlockFromChatFrame()


[edit] BlockFromDelegate(delegate)

  • Parameters: the delegate to block delivery of event from.
  • Returns: success(boolean:true/false), error_msg(string)

Block the event from being delivered to a delegate. Useful, if you want your app to ignore an event but want it to continue to be delivered to everyone else.

Note, an error is returned if an invalid delegate is provided.

Example:

eventController:BlockFromDelegate(delegate)


[edit] GetNumDelegates()

  • Returns: integer

This call is used to receive the number of delegates handling this event.


[edit] GetDelegate(index)

  • Parameter: integer
  • Returns: delegate


[edit] Allow()

This is here for convention but has no control over the event. Calling this is the same as not doing anything to the eventController.

Example:

eventController:Allow()


[edit] Suspend(delegate)

  • Parameters: the delegate taking responsibility for suspending this event.
  • Returns: success(boolean:true/false), error_msg(string)

Suspending a event tells LibChatHandler-1.0 to hold off on delivering the event for now, it should be delivered later. This is particularly useful for addons such as a spam blocker which would like to do a who lookup on the sender prior to assessing if the message should be delivered or not. Note that the delegate suspending the event must be passed as the parameter since only suspended events can be released by the delegate who suspended it originally. Multiple delegates may suspend the same event, however the event will only be delivered once it has been released by all the delegates currently holding it.

This call will fail only if the delegate passed is invalid.

Example:

-- save a pointer to this event for later processing
eventToBeHandledLater = eventController

-- suspend the event from being delivered.
eventController:Suspend(delegate)


[edit] Release(delegate)

  • Parameters: the delegate taking responsibility for releasing this event. Note: the delegate must be the one who initially suspended the event.
  • Returns: success(boolean:true/false), error_msg(string)

Releasing an event tells LibChatHandler-1.0 that the delegate has finished processing the event and is ready to be delivered to the viewer. A release must be called on a suspended event no matter what action is called upon it. For example, if you have determined that the event should be blocked, you must still release the event so it may be processed and cleaned up within LibChatHandler-1.0.

This call will return an error if the delegate was not responsible for suspending the event.


Example:

-- Remember we set eventToBeHandledLater in Suspend()'s previous example
eventToBeHandledLater:Block()
eventToBeHandledLater:Release(delegate)

If you decided the event was ok, and should be delivered as necessary you could have changed Bock to Allow or simply

-- Remember we set eventToBeHandledLater in Suspend()'s previous example
eventToBeHandledLater:Release(delegate)

[edit] Examples

The documentation might seem a little overbearing but it is easy none the less to implement. Below are some examples of how the library is used.

[edit] Example 1

Below is an example of how a chat addon who simply needs to capture whispers can be used. This addon does not need to control any events, it simply wants the events to be delivered to it.

-- This addon is really simple, lets make a new delegate.
MyWhisperAddon = LibStub:GetLibrary("LibChatHandler-1.0"):NewDelegate();

-- register chat event
MyWhisperAddon:RegisterChatEvent("CHAT_MSG_WHISPER");

-- this is our viewer. if the event was received, it is delivered here
function MyWhisperAddon:CHAT_MSG_WHISPER(message, from)
   message("Whisper Received!\nFrom:"..from.."\nMessage:"..message);
end


[edit] Example 2

In this next example, we want to achieve the same thing, but we already started our addon using Ace3 and want to now receive events for whispers.


--import our library
local libCH = LibStub:GetLibrary("LibChatHandler-1.0");

-- make my ace3 addon a delegate.
libCH:Embed(MyAce3Addon);

-- register chat event
MyAce3Addon:RegisterChatEvent("CHAT_MSG_WHISPER");

-- this is our viewer. if the event was received, it is delivered here
function MyAce3Addon:CHAT_MSG_WHISPER(message, from)
   message("Whisper Received!\nFrom:"..from.."\nMessage:"..message);
end

[edit] Example 3

In this example, we want to pop up a message whenever we receive a whisper containing the world "gold" and to not display it in Blizzard's chat frame. To do this we need to modify our first example by adding a event controller.

-- This addon is really simple, lets make a new delegate.
Gold = LibStub:GetLibrary("LibChatHandler-1.0"):NewDelegate();

-- register chat event
Gold:RegisterChatEvent("CHAT_MSG_WHISPER");

-- this is our controller, this is where we tell the message not to be shown by Blizzard's chat frame.
function Gold:CHAT_MSG_WHISPER_CONTROLLER(eventController, message, from, ...)
    if(string.find(message, "gold")) then
        eventController:BlockFromChatFrame()
    end
end

-- this is our viewer. if the event was received, it is delivered here
function Gold:CHAT_MSG_WHISPER(message, from)
    if(string.find(message, "gold")) then
        message("Whisper Received!\nFrom:"..from.."\nMessage:"..message);
    end
end


[edit] Example 4

In this example we will introduce how Suspend and Release works. Again working with whispers, we are going write a simple level based filter, blocking any message received by a level 1 user. This example will make use of an library called LibWho-2.0, a who look up library. For more information on this library, you can look it up at [1].

-- get LibWho
local libWho = LibStub:GetLibrary("LibWho-2.0")
-- get LibChatHandler-1.0
local libCH = LibStub:GetLibrary("LibChatHandler-1.0")

--create delegate
local levelBlocker = libCH:NewDelegate()

--register event
levelBlocker:RegisterChatEvent("CHAT_MSG_WHISPER")

--the controller for CHAT_MSG_WHISPER
function levelBlocker:CHAT_MSG_WHISPER_CONTROLLER(eventController, message, from, ...)
    eventController:Suspend(levelBlocker)
    libWho:UserInfo(from,
        {
            queue = libWho.WHOLIB_QUEUE_QUIET,
            timeout = 0,
            flags = libWho.WHOLIB_FLAG_ALWAYS_CALLBACK,
            callback = function(result)
                 if(result.Level == 1) then
                     eventController:Block()
                     eventController:Release(levelBlocker)
                 else
                     eventController:Release(levelBlocker)
                 end
            end
        });
end



[edit] Other Information

Personal tools
statistics
People Online: 12
Today's Visitors: 299
Total Visitors: 2,753,103