Official development blog

Roguelike-Discord Integration Using Webhooks

When Cogmind’s first commercial version was released in 2015, I simultaneously opened the brand new Grid Sage Forums as the main gathering point for the community, a way to share stories, provide feedback, and generally discuss the game. Back then forums were still one of the most common ways for game communities to interact, and I also wanted to maintain such an outlet over which I had complete control (i.e. on my own server and with my own settings and design) rather than making a home under the umbrella of some other company where we’d be subject to their whims over the long term.

grid_sage_games_forums

The good old GSG forums!

Well… after a year of navigating Cogmind’s early alpha progress with the community on the forums, which were pretty active over that year, Discord came along and became that “other company” xD

Of course the product is different, and therefore we can easily see why it could do such a thorough job of supplanting the forums--it’s simply better suited to this sort of use, hence the now huge majority of games that use it to build engaging communities. Faster, easier real-time communication with devs and other players alike, together with more natural support for multimedia… I guess forums didn’t stand a chance xD

Interestingly, IRC could have been seen as an alternative, or supporting, possibility for community interaction, and there were some who wanted to do that when Cogmind was first released (I was there, too, for a short while), but we have to admit IRC is just not as good for most people--Discord essentially took IRC and made it more easily accessible to the masses, which is apparently exactly what the masses wanted and needed.

For a while myself and a few other players tried to keep the forums active, but the community drive to relocate to Discord was swift and unstoppable…

The forums are technically not dead dead--they still get used as a more official repository for bug reports, or by someone who wants to post something to a location more permanently and easily accessible to all. It’s also my primary outlet for official announcements (this is noticeable when, for example, my release notes are too long to fit on Steam so I link to the forums where I can share them in their full glory because, again, I control the settings to allow that :P). And we use the forums for the occasional REXPaint feature/help discussion, so yeah they have their uses even now.

Roguelikes Discord

Back in mid-2016 a couple of friends decided to make a new Discord server on the topic of roguelikes, and started asking relevant devs like myself to join. I decided to try it out, and it was kinda neat being able to chat with other roguelike players in real time (oh no, we moved further away from turn-based chatting?!).

The Cogmind community started showing up there pretty fast, draining active participants from other outlets (including the main forums, subreddit, and relevant threads on other forums) since it was just so much more natural and enjoyable to engage others via flowing conversations rather than delayed posting and repeated reloading of web pages.

The server became the home of many traditional roguelike communities (small as they may be), and also the “official” Cogmind server, which I like to keep embedded there with all the other roguelikes.

roguelikes_disord_cogmind_channel_list

Current #cogmind channels on the Roguelikes server. We ended up adding more and more Cogmind channels over the years, though most are hidden from the average server member so it’s not too annoying unless they’re actually there for Cogmind content :P

Seven years later we’re still there, with a lot of the same folks cycling in and out over short or long periods, and veteran players mentoring newer ones. We also often get interested in other roguelikes on the server and play those :)

Anyway, Discord definitely has its drawbacks, but it works well as a primary communication tool for gaming communities so it’s no surprise its use has exploded over the years.

Discord Integration?

When a community is heavily concentrated in any one form of social media, you naturally start to think about leveraging that platform to encourage community interaction and improve the overall experience. Discord itself of course wants to capitalize on this effect and promote related features, so it provides an SDK for doing such things.

The first feature some might imagine with regard to using the SDK is at least some form of so-called “Rich Presence,” which is what I considered a long time ago when players asked about that as a possibility. But I didn’t want to bloat the size of the game just for that--didn’t seem worth it.

On the contrary, at the time I realized that I already integrated the Steam SDK by necessity (and it’s a separate build from the DRM-free release, therefore only affecting those using Steam to begin with), so I figured it might be low-hanging fruit without any drawbacks to at least introduce Steam’s Rich Presence as a fun little side project. I did that in 2019 and wrote about the process here.

But integrating with Discord never appealed to me.

Then I learned more about webhooks and had an idea.

Webhooks!

It turns out you can technically do a form of Discord integration without their SDK, using these “webhook” thingies…

Now I’m sure this was obvious to people versed in Discord or even online platforms in general, but even having seen some in action I’d never really known how webhooks work, me being generally ignorant of web dev.

I forget what it was that triggered the realization, but some weeks ago I became aware that 1) without embedding the Discord SDK I could 2) simply have Cogmind send messages to the Discord server, and that was all I needed to know to come up with a potentially cool new feature ;)

Discord’s dev resources cover everything you need to implement webhooks, at least on their end in terms of what you can do and how to format each type of data. On the game side you’ll most fundamentally need a way to make an HTTP POST request to provide the message text. That’ll be handled differently depending on whatever languages or libraries you’re using, so I won’t cover that here.

One important consideration worth mentioning if you plan to send a lot of messages, and want all of those messages to actually be posted: You’ll need to have a way to handle webhook rate limits.

I got my first Cogmind-Discord interface all set up and properly sending messages that appeared on my test server, then I tried to do a bit of stress testing to simulate extreme scenarios only to find… not everything was appearing xD. Okay yeah that makes sense.

roguelikes_discord_cogmind_activity_webhook_stress_test

Me typing to myself in my solo test server as I was building this feature :P

So rather than firing off messages as soon as the game wanted to send them, I had to go back and rewrite it such that 1) there’s a message queue and 2) Discord’s server response is actually checked to see if the last message went through and 3) if not, what’s the requested retry delay and wait that long before continuing with the queue. A little more complex, but good to get that out of the way before releasing this feature to players then having it be an obviously substandard experience!

Fortunately there weren’t many technical hurdles to clear, even for webdev-challenged me. It helped that most of the heavy lifting could simply leverage all the past work on my HTTP interface and multithreading functionality, as I couldn’t see myself wanting to dive into this if I didn’t already have that foundation in place. As is it really was a nice little side project that didn’t suck up a ton of time and could comparatively provide the community with a cool new feature.

Content

Now that we have the ability for the game to post messages, what do we post? What’s relevant for a roguelike? And where does this content go?

First of all, since there could theoretically be a lot of messages coming in, and they could come in at any time, to avoid interrupting normal conversation in the server channels it makes sense to give the output from this thing its own channel. Thus #cogmind-activity was born.

We can still chat there, of course, just generally it would be in response to the info coming in, or even just drop emoji reactions to various events, overall new ways to interact with other players’ runs in progress (or that have recently ended) without them having to actively share any info like a summary or screenshots.

roguelikes_discord_cogmind_activity_icon_scene

Webhooks need an icon to represent the bot, so I threw together a weird, uh, activity scene using random little things my son has collected, alongside my 3D-printed Cogmind from Runia.

I also added a way for the player to manually specify a Discord webhook of their own choosing, in order to redirect all the output from their game to some other server or channel they’ve set up.

As for the meat of the feature, what we’re posting…

Scoresheets

One of the most basic and frequently shared pieces of info about a run is a link to the online scoresheet, which contains a highly detailed summary of pretty much every aspect. I wrote a lot about these scoresheets back when they were further expanded in my Ultimate Roguelike Morgue File series.

This is also the first thing I was thinking with webhook use--players are often sharing these links manually, and the game knows the link, so why not just make it happen automatically for those community members who want to do that?

roguelikes_discord_cogmind_activity_run_summary

A sample run summary output in the wild, including scoresheet links and more.

In addition to the automated link sharing, you can see I also included a short summary of core run data, including final score, difficulty setting and any special event mode, the number of regions visited (good for getting an idea of how long the run really was), and the number of robots destroyed (useful both to show off as well as telling a lot about a run when compared with how many maps they passed through).

Then of course it’s important to know how the run ended, as in whether they were destroyed (and how) or won (and in which way, since there are many win types).

After the links I thought it might also be fun to directly include a printout of their final build state, as taken from the scoresheet itself.

In the above screenshot, notice how the webhook’s name is actually using the player’s name, in this case “szymekc.” This is one of many possible features offered by custom webhook data, and the alternative would’ve been to leave the webhook name static and instead include the player’s name as part of the message itself, but 1) that wastes space and 2) when there are messages from multiple players being posted in close proximity, this approach can make it a little easier to distinguish which run is which (an issue you’ll see come into play soon here).

Achievements

Although each player will only earn each achievement once, there are quite a few in Cogmind (and even more to come!), and many are quite special, so we may as well report on these as well. It’s also the kind of thing players tend to share on their own, having accomplished some significant feat, or even an unexpected or funny minor one, which means another area where automation might be able to contribute to the community.

roguelikes_discord_cogmind_activity_achievement_sample

Achievements appear bracketed and in italics.

History Log… in progress!

One of the major new scoresheet features described at length in part 4 of my Morgue series, Cogmind’s “history log” is meant to read as a sort of story-like summary of an entire run, highlighting special events, important accomplishments or changes, or otherwise potentially interesting or informative bits about the run.

It indeed works out as a pretty nice written review of what transpired, outside what typical numerical data and lists can show, though as is it’s of course something the player, or others, would read after a run is completed (or I guess it’s possible during the run, too, via mid-run stat dumps).

You can see where this is going. Once I got to thinking about what more could be offered via the webhook beyond the normal go-tos, the history log really popped out as an enticing option. We already have the power to describe much of what’s going on in words, let’s use it! So instead of just appearing in the post-run log, now each history message is pumped to the #cogmind-activity channel as it happens in real time.

roguelikes_discord_cogmind_activity_history_logging_sample1

Sample reporting of runs in progress from the latest build currently in prerelease testing.

 

roguelikes_discord_cogmind_activity_history_logging_sample2

Another history logging sample from #cogmind-activity.

Already we’ve already seen plenty of commenting on particular points during runs, whether from the player themself, or others in the community following the runs, posing questions or making observations. It’s also an alternative way to intermittently follow runs in progress when someone is streaming via Twitch or voice chat, when maybe there’s not enough time (or large enough display on hand :P) to watch the full stream.

As part of this update, I made it possible to set exceptions for some history log messages that I didn’t think needed to be reflected on Discord as well, somewhat less meaningful ones or those that could otherwise seem spammy. It’s not necessarily one single run we’re seeing, after all, but potentially multiple or even numerous runs that could be threaded together, so cutting away a bit of the excess is desirable.

Who knows, maybe seeing the history log output in this format and context might even lead to further adjustments and improvements to its content, now that we have even more direct contact with it, and in a communal space. Either way, there are certainly different thresholds for what we want to include in different environments.

Improvements

This whole feature has only just been added for the latest Beta 13 build released for playtesting among patrons, and being a relatively small side project it didn’t exactly go through the complete process of what all can we do with this newfound power?! As such, there are improvements I’m still considering, as well as some that were considered but left out (for now, pending indirect feedback).

Spoilers

One of the biggest dilemmas during the design of this integration was what to do about spoilers. Cogmind being a game that lends itself to long-term exploration and discovery, sharing and discussion between players is stratified into a few distinct levels of spoilers that the community does a good job of maintaining to respect the desires of many players to remain unspoiled until they discover content on their own.

In that light, it would make sense to, for example, apply Discord’s spoiler tags to all relevant content shared via the webhook to #cogmind-activity, making it so that anyone could hang out there without fear of being spoiled.

Unfortunately that would be a fair bit more work to achieve, and could also get kind of annoying with all the spoiler tags, so for now I decided the channel is basically full redacted content, no-spoilers-barred territory. Basically it’s read at your own risk, indicated in the channel description, which might cut down on participation there, but I think it’s the most realistic option for now.

Color

Another factor I considered while building it, and again revisited after it was released and I could see it in action with multiple players, was how to better differentiate runs when more than one is happening at the same time.

It seemed like color could be a potentially useful differentiator, where each player has their own randomly selected color for their run (from among reasonable/readable options :P), and all messages from that run appear in their color.

Unfortunately Discord does not support colored text via any sort of easy inline markup. There are several workarounds to apply color to text, namely by using code blocks and their associated syntax highlighting, or the newer colored ansi feature, or you can even get creative and insert some color before the text with embeds, but none of these approaches were meant for such a purpose, so of course they don’t do it well.

roguelikes_discord_cogmind_activity_colored_mockup

Using ansi color codes, which also forces fixed width code blocks, just takes up so much room… meh.

An embed-like approach with a simple color before each line of text could be a nice non-intrusive solution (if such a feature existed), since then entire text doesn’t have to assume that color and potentially be harder to read…

Actually, on that note, what about emoji? Oh my, the possibilities. Now that I think about it, it might be fun to allow players to optionally specify an emoji to represent themselves, which would appear before every webhook-delivered message of theirs and make it just a little easier to follow runs when they are overlapping, not to mention just being fun to play with/customize how your run appears.

At the simplest level, instead of picking their emoji maybe we can assign one randomly to each player for their run (which could of course be entertaining in itself, including for the player :P).

And how many types of colored blocks do we have access to? Since those could be an alternative to the embed idea, prefixing run-specific lines with simply an associated color. Accessibility concerns of course imply we should do this with full emoji rather than just color, considering we presumably have access to the full array. Imma go test this because it sounds cool…

roguelikes_discord_cogmind_activity_emoji_test

Emoji test. Yes… YES!

Okay I think we might be seeing more of that later :)

Other Supported Features

Discord webhooks are surprisingly powerful, and based on the API docs it appears there are additional possibilities we can tap into, like theoretically uploading game screenshots. To that end, perhaps there’s a way for the player to enter commands that control the webhook, such as when they want to manually send images or other info. Definitely more complicated, but interesting to think about.

The webhook’s avatar could also be modified for each player, doubling as a form of run differentiator, though this is only useful to those users displaying avatars, so maybe not ideal since it’s not universal, and could also get a bit confusing for some people when actual users show up to chat about runs and get mixed in. In that case it’s probably better if the webhook maintains a consistent icon, since its name is already changing, after all.

Another idea I experimented with was using code blocks to draw ASCII art that could make for fun viewing, like at the end of a run or to otherwise highlight interesting events, but while it’s neat I didn’t feel like the amount of effort required would really be worth it in the end.

While there’s more adjustments likely to come, at this point I think it’s safe to say mission accomplished, welcome to another cool community feature :D

This entry was posted in Gamedev and tagged , . Bookmark the permalink. Trackbacks are closed, but you can post a comment.

Post a Comment

Your email is never published nor shared. Only the anti-spam entry is required. See here for the privacy policy.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>