Looking for more active discussion? Join our Discord at https://discord.gg/x2s7fY6

How to shot GMCP

LinLin BlackbirdThe Moonglade

What is GMCP?

Glad you asked, gov'nor. GMCP stands for Generic MUD Communication Protocol. It's an underlying communication layer sent to your MU* client in addition to the usual text-based output. In simpler terms, it's a wealth of information about your character and their environment, that updates in realtime as you play.

Aetolia (and other IREs, for that matter) send this info to your client in this order:
  • Primary events (gmcp.Room, gmcp.Char, ...)
  • Secondary events (gmcp.Room.Players, gmcp.Comm.Channel.Start, ...)
  • Output text (what you typically see on your screen)
  • Telnet GA sequence (the prompt)

How do I access GMCP data?

Interpretation of GMCP data will vary by client.

image
  • To enable GMCP in Mudlet, navigate to Options --> Preferences and view the main General tab. Make sure the checkbox marked Enable GMCP is enabled, and restart the program.
Mudlet catches this GMCP data and populates the following table: gmcp. Remember, Lua is case sensitive. It's not GMCP or Gmcp, it's gmcp. The gmcp table is further divided into sub-tables representing each module: Char, Room, Comm, and others.

When gmcp is updated, Mudlet raises an event for every single table within gmcp. For instance, when you take damage or level up, gmcp.Char.Vitals is updated with new health or XP information. Mudlet also raises an event, which itself is called gmcp.Char.Vitals.

This system of updating and event raising is practically enough to build an entire comprehensive system!

How do I use events?

Lua is a scripting language with extensibility in mind. When implemented in applications like Mudlet or World of Warcraft, its purpose is to act as a layer on top of whatever the program was written in, to provide the end user with an easy and intuitive coding interface that they can use to modify the application.

Events have many implementations, but one of the chief uses is to signal to the Lua interface that the program has done something. A very common Mudlet example is the window resize event, which is raised every time you move or resize your Mudlet window. This event is hidden from the user, but a function exists to help us use it: handleWindowResizeEvent().

What we're going to learn here is how to capture GMCP events, for the purposes of using them in our system.

Navigate to your scripting window:

image

And let's make a new script:
  • (yes, my Aetolia profile is named Lusternia, it's a long story)
image
  1. Create a new script.
  2. Make sure it's activated! Click the lock icon on the left.
  3. Name the script. IMPORTANT: There MUST be a function in the script file with the exact same name as this script page for this to work!
With our new script page created, we're gonna add some events that we want to capture. For the purposes of demonstration, I'm going to keep this one super simple. We'll make our system respond to the Room information being updated, and our Character information being updated.
image
  1. Type in the name of the event(s) you want handled. This must be the exact same name of the gmcp sub-table you want and IT IS CASE SENSITIVE.
  2. Enter each one and hit the plus (+) button to add the event.
Now, at this point, we have a fresh new test script and we're watching these events! There's only two steps left to go: We need to add our handler function (the one that shares the same name as the script page), and then write a little code to show that it's all working okay.
  • I'm gonna show you how this is done, but you have to write it yourself!
image

Now, here's how this madness works:
  • Every single time gmcp.Room and gmcp.Char are raised (you move into a room, you look into a room, you take damage, you check your SCORE, you receive a prompt, etc.), this script page will call the handler function, in this case, handleTestEvent().
  • When a handler function is called, the first argument (that's the stuff that goes between the parentheses in a function call) is the name of the event that called it. As you can see in handleTestEvent(), our first argument is passed as "e", and you can see how we're checking to see whether "e" was gmcp.Room, or gmcp.Char. If either one checks out, we're going to call functions made just to handle those, listed below. You can also just pop your code into the handler function, but I think this is cleaner.
  • When we get room info, we're going to get a gold echo.
  • When we get character info, we're going to get a subdued but equally hard working red echo.
Make sure to save your script, and then try it out in-game. Here's how it works for me:

image

As you can see, our information should be coming up properly!

So why are the echoes firing so much?

In this example, we handled two events: gmcp.Room and gmcp.Char. The problem with this is that these are primary modules, and are, in fact, made up of several secondary modules. Let's take a look, for instance, at what is actually being passed from gmcp.Room:

image

As you can see, gmcp.Room is divided into two secondary modules: gmcp.Room.Info, and gmcp.Room.Players. When we handle the event gmcp.Room, we not only handle that event, but every event beneath it.

This is why we're getting two golden echoes in the image above; one is the room's statistics being raised, and the other is a list of players! The same is occurring with gmcp.Char: We're actually seeing events raised for gmcp.Char.Vitals, and gmcp.Char.Status.
  • gmcp.Char actually contains a lot more secondary events (Items, Name, Skills, and StatusVars), but these are only raised under special circumstances.


So how do we make this more efficient?

Divide our handled events into their respective submodules. I prefer to maintain a script page for each primary module (one for Room, one for Char, etc.), with a handler that works with each submodule, but let's be lazy and just modify our test module to make it more specific.

image

With this structure, we only care about two bits of information: Players in the room, and our vitals. I'll leave it to you to try this and see what it does, but it's guaranteed to be a lot less spammy!



So, this concludes my little tutorial on how to play with GMCP. If you have any questions or want to throw out some pointers, please feel free to do so.
TozAldricLiancaHavenEzraxMoireanSetneBakhtuhEzalor

Comments

  • LinLin Blackbird The Moonglade
    For the very dull, by the way, this thread title is based on How Do I Shot Web.
  • SetneSetne The Grand Tyrant
    110/10, would recommend.

    Ingram said:
    "Oh my arms are suddenly lubed"
  • i come here for a nice, pretty laid out list of the GMCP info...and YOU DIDN'T DELIVER!!!!!
    image
    Moirean
  • @osmond
    If you use mudlet...

    put: display(gmcp)
    into a script/alias/whatever

    Then read the output, which will be printed to the main window.
    If you use a different client, you'll need to look into your client's help files to learn how it handles gmcp.

    gmcp is a table, which Mudlet keeps updated for you.


    @Lin
    Do you have a list of little-known gmcp modules which are not enabled by default, but which might be amazingly, life-changingly useful? I vaguely remember learning about one last time I was playing, but I don't remember what it might have been.
  • LinLin Blackbird The Moonglade
    Not a list per se, but here's what I use to expand GMCP's functionality:

    Cache Support


    Plant this in a top-level script (literally a script page at the top of the list, so it loads early as possible):

    sendGMCP("core.supports.add \[\"IRE.Rift 1\"\]")
    send(" ", false)



    Request Functions


    You can insert these into "hooks" (aliases designed to replicate an in-game command, but add a little somethin'-somethin') to get the game to update its info for you.

    RefreshInventory = function ()
    	sendGMCP("Char.Items.Inv")
    	send(" ", false)
    end
    
    RefreshPlayers = function ()
    	sendGMCP("Comm.Channel.Players")
    	send(" ")
    end
    
    RefreshCache = function ()
    	sendGMCP("IRE.Rift.Request")
    	send(" ", false)
    end


    Using the Hooks


    Try these aliases!

    Pattern: ^(?:i|inv|inventory)
    RefreshInventory()
    send(matches[1], false)

    Pattern: ^(?:q|b)(?:w|who)$
    RefreshPlayers()
    send(matches[1], false)

    The cache seems to update fine without needing a hook for it, but I included that request function above just in case.
  • I know how to look up the GMCP tables, I just wanted Lin to go uber try hard and make it all nice and neat and pretty on here.
    image
  • LinLin Blackbird The Moonglade
    image
    Haven
  • HavenHaven World Burner Flight School
    I love me some Emma Watson.
    ¤ Si vis pacem, para bellum. ¤
    Someone powerful says, "We're going to have to delete you."
    havenbanner2
    SetneOleisDraiman
  • Creepy.
  • LinLin Blackbird The Moonglade
    edited July 2013
    As promised in the IRC Q&A, this is all you need to stay AFK indefinitely:

    image

    Remember, it's case-sensitive!
  • Thanks Lin. Nice and easy.
  • LinLin Blackbird The Moonglade
    Just like your girlfriend.
    TreydenAlice
  • MoireanMoirean Chairmander Portland
    Fairly old bump, but I was wondering if there is just a basic list somewhere that people from all different clients could look at to just see what part of gmcp calls what. Eg, gmcp.room.info.name pulls up your room name.
  • There's the IRE GMCP doc - http://www.ironrealms.com/gmcp-doc 
    For beauty is nothing but the beginning of terror, which we are still just able to endure,
    and we are so awed because it serenely disdains to annihilate us.
    Every angel is terrifying.
    MoireanIvoln
  • DaskalosDaskalos Credit Whore Extraordinare Rolling amongst piles of credits.

    Trying to get this to hook into cmud but I can't seem to get rift data to populate. This is all the stuff I'm -trying- to get to load:

    Core 1
    Char 1
    Room 1
    Comm 1
    IRE.Composer 1
    IRE.Rift 1
    IRE.FileStore 1
    IRE.Misc 1
    IRE.Wiz 1
    Comm.Channel 1
    Char.Items 1
    Char.Skills 1

     

    image

    image


    Message #17059 Sent By: Oleis           Received On: 1/03/2014/17:24
    "If it makes you feel better, just checking your artifact list threatens to crash my mudlet."

    Rodala
Sign In or Register to comment.