Nexus GMCP Events

This is a small reflex package that turns GMCP messages into events so you don't have to deal with onGMCP and can avoid having a million scripts separately checking "if (args.gmcp_method === "Char.Vitals")".

Explanation:

Let's say you want to display a notice every time your health changes.

First, you set up a variable to remember your health:
var old_health = 0;
Then we need a function that takes our vitals from GMCP, looks at the new health number, compares it to our old health, and displays the difference. This function will see if the health changed, and if it did it will print out the amount of change in red.
var health_change = function (char_vitals) {
    var new_health = char_vitals.hp;
    var health_difference = new_health - old_health;
    if (health_difference !== 0) {
        client.display_notice("Health change: " + health_difference, "red");
        old_health = new_health;
    }
};
Now we need some way to call this function every time we get a GMCP message with our health in it. Normally in Nexus, this would mean making an onGMCP function and running "if (args.gmcp_method === "Char.Vitals") health_change(args.gmcp_args)". And for every function we want to run on Char.Vitals, we need to pile it all under one "if (args.gmcp_method === "Char.Vitals")" or we have to do a separate test on every GMCP message for every script.

What we really want is for each GMCP message to be its own event.

With gmcp_events, instead of mucking around with onGMCP and checking to see what kind of GMCP message every GMCP message is, all we have to do is add a listener for Char.Vitals:
var health_change_listener = gmcp_events.subscribe("Char.Vitals", health_change);

Now every time the client receives a Char.Vitals GMCP message, it will run our health_change function (automatically passing it the gmcp_args).

If we want to turn this off, we can just remove the listener:

health_change_listener.remove();




Summary:

To add a listener, use:

gmcp_events.subscribe("GMCP Method Name", myFunction);

This passes args.gmcp_args as the first argument to myFunction and it returns a handle that can be used to remove the listener.

Adding a listener and saving the handle so we can remove the listener later:

handle = gmcp_events.subscribe("GMCP Method Name", myFunction);

To remove a listener, use:

handle.remove();

Comments

  • Nicely done!
    One usability and one feature suggestion:
    - Make the gmcp messages all lower case all the time. This will help people who are new-ish to gmcp and coding.
    - Allow the subscription to "event groups" in one go. Say I want to catch all Char.Items messages (Char.Items.Add, Char.Items.Remove, Char.Items.List, Char.Items.Update) in one function and branch out from there. Then I'd like to subscribe to Char.Items instead of all messages individually. In that event, you may want to hand the actual gmcp message as a second argument to the function.
  • Keneanung said:
    Nicely done!
    One usability and one feature suggestion:
    - Make the gmcp messages all lower case all the time. This will help people who are new-ish to gmcp and coding.
    - Allow the subscription to "event groups" in one go. Say I want to catch all Char.Items messages (Char.Items.Add, Char.Items.Remove, Char.Items.List, Char.Items.Update) in one function and branch out from there. Then I'd like to subscribe to Char.Items instead of all messages individually. In that event, you may want to hand the actual gmcp message as a second argument to the function.
    I'm not totally sold on the idea that the GMCP message names would be more straightforward if they were different than the names actually are in reference documents or with the client set to show GMCP messages.

    And I'm not really sure I understand the second request. Char.Items.Add and Char.Items.Remove, for instance, have the same syntax for their data, so you have to use the name to distinguish between them. Passing the whole GMCP message as the second argument just so someone can subscribe to both of them at once, then just end up using that second argument to test the event name seems like it defeats a lot of the purpose of the whole thing. I don't think it's very easy to do given the way Nexus is written either - getting the "gmcp_method" and the parsed "gmcp_args" is easy. But to get the actual message I think I'd have to monkey-patch the internal GMCP-handling code and it's pretty ugly.

    In the hypothetical situation where you want to do the same thing when you receive Char.Items.Remove and Char.Items.Add without distinguishing between them, it seems a lot clearer to me to have two subscriptions with the same function. And if you want to do something that differs between the two, it seems a lot clearer to me to have two subscriptions there too.
  • Fixed a small error that made removing the last event listener for a given type of GMCP message impossible.
Sign In or Register to comment.