Home Artists Posts Import Register

Content

Last year Steam updated its friends list and chat client to support  more features, and among them is support for "Rich Presence," or  basically giving games running under Steam the option to share with  friends more about the player's current state.

^My Cogmind Rich Presence status as seen in someone else's friends list while I was testing it out.

As you can see I've now added this feature to Cogmind for the next release :)

Exploring  the potential for this feature had been on my TODO list for a good six  months since I'd first heard about it, though it just sat there slowly  sliding its way to the top as I ticked off higher priority features for  Beta 9.

I don't normally use Steam as a consumer--I only started  using their platform for development purposes, but not regularly enough  to even notice Rich Presence in action, so that also made it less likely  I'd promote the feature in the near term. Then more recently another  player brought it up, and at the time I had a free evening and felt like  doing a little mini-project, so I decided to give it a boost to the  top...

Steam actually makes it extremely easy to do this (unlike  Discord, which was also on my list but I dropped it earlier after doing  some research, which is kinda funny since reportedly Steam finally  rebuilt its friends/chat UI in response to competition from Discord...).  You can read about Rich Presence in the Steamworks documentation, though I'll be covering its main features and my own experience with it here as well.

Content

First thing to consider is exactly what kind of text should be shown for the player's status in Cogmind?

Back  when I initially jotted it down on my TODO list, the most obvious  answer at the time was simply their location, as usual in a format like  "-7/Factory." But with the launch of Beta 9  we also have some great new features that would be perfect here: build  class and status summary! Originally devised for the purpose of helping  contextualize mid-run stat dumps,  classes also became a multi-section feature of the final scoresheet,  and build class was even later expanded with an optional HUD display.  Now these features can perform double/triple duty by including them in  the rich presence string.

Why just show "-7/Factory " when we could show "Playing as Hacker-Skirmisher in -7/Factory. Status: Great"?

The Rich Presence possibilities now seem pretty colorful compared to showing only location, but will it all fit?

That  was my next question, just how much room is there to display stuff, and  unfortunately Steam's docs are actually not too clear on this point,  just saying that if it's too long it'll be truncated or ellipisified  (which are sorta two different things, the latter possibly implying it  could be expanded and the former suggesting it can't, but anyway...).  The docs don't get specific enough to base a real decision on, so I did a  little research to see what would show for other games.

It turns  out longer strings that don't fit are okay, since users can see the full  string by expanding the friends list if necessary, although it's  important to remember that users might only see the first 2~3 words  unless their friends list is sized a little wider than the minimum  allowed width. (You can see an example in my first screenshot above of  the width required to show that string.)

Users who hover over a friend's avatar can also see the full details, which are just split up into multiple lines like so:

^Steam friend details with full multiline Rich Presence string.

So  the first few words are going to be the most important in the string,  and we could technically pack even more information in if we're willing  to abbreviate. That said, while abbreviations are great for players  already quite familiar with the game, I'd say Rich Presence is also  useful in that it can be suggestive to friends who have never played the game, so non-standard abbreviations are best avoided.

As  a traditional roguelike, most of Cogmind is spent controlling the main  character rather than having a bunch of separate modes, so the vast  majority of Rich Presence strings will simply be of the  [build][location][status] variety. 99% of the playtime is covered there,  and I ignored the intro/title for now (actually maybe I should just add  an "Enjoying the animated intro" status for fun :P), so all that's left  is the game over screen. Fortunately this didn't require a bunch of  extra work because the new scoresheet header  now includes the "Result" of the run as a string, which in addition to  the "win result strings" we've had before was recently updated with even  the specific cause of death. Behold:

^Steam friend details with cause of death while viewing the game over screen.

Implementation

The  technical side of things is actually quite simple, it's almost just  calling a single function to notify Steam of a new Rich Presence string,  although as you'll see there's a bit more to it than that.

Before  building proper architecture for this feature, I just wanted to call  the SteamFriends()->SetRichPresence() function with some dummy text  and see it working at a basic level. Other than the function call, doing  this just requires one other step: Defining the available strings in a  text file uploaded to the Steamworks backend.

Maybe they'll  correct it at some point after I post this, but I discovered that the  sample file in the general docs for this feature actually has a  formatting error that prevents it from working. I found the proper  format on the dedicated localization section of the docs.

Testing what was and wasn't working was fairly easy, however, since Steam provides a useful Rich Presence testing page  (for devs who are logged in and playing their own dev build, even off  Steam). It'll display any errors encountered while trying to load and  set Rich Presence data.

^Using Steam's Rich Presence Tester page for devs.

This  whole process was pretty quick, probably the only slight roadblock was  figuring out what to put on the backend without having to upload a bunch  of different strings--ideally everything should be handled in game.  (The docs are focused more around localization and fairly modal games,  rather than my own needs here.) Cogmind doesn't have localization, nor  does it have a strong need to have a bunch of different "tokens"  representing different modes, so I took a different approach: I have  only one language, with one token, and it contains no text just a single  variable :P

^Simple  "localization" workaround for Rich Presence in Cogmind, that way I can  just drop whatever string I want into the %text% variable and that'll be  the player status.

If you're interested in how it's really done when you have multiple languages and more modes, check out the localization docs.

With that in place on the backend ready to accept non-static data, it's time for proper architecture...

^SteamRichPresence header (this should be a class rather than a struct but I'm lazy here since it's not going to hurt).

There's  so little logic involved in setting a presence string that I started by  simply updating it directly from where I wanted to check it in game,  but after testing a bit discovered I'd need a second check elsewhere so,  sure enough, going the smarter route of centralizing the code into its  own thing was clearly the better option. So that simple class was born.

Technically  it's ultimately faster to update this only when necessary, i.e. at the  point of a change, but a centralized solution is much simpler to manage  across multiple systems, checking every 5 seconds whether the current  string should be updated or not. It Just Works, since all the relevant  code is contained within the update() routine, and you don't have to  worry about it elsewhere.

^SteamRichPresence update() method source.

The  code is pretty straightforward: After figuring out what the string  should be, if it's different from the most recently uploaded value, it  loads the new string into the "text" variable, then writes the  #StatusFull token (which as per the definition specified in the earlier  file is nothing more than the text variable!) to "steam_display," which  Valve has designated the target for displaying a Rich Presence string  for the player.

After this it was just a matter of testing the different scenarios to confirm they actually work.

Rather  than repeatedly going to the tester page or my friends list, once the  data seemed like it was uploading normally I also implemented a little  in-game indicator for debugging so I could more quickly see what Cogmind  was sending to Steam:

^Testing Rich Presence updates with debug view active.

Once  it's all working there's still one more bit: an option to turn it off!  Rich Presence reporting is on by default, but maybe not everyone wants  to advertise to their friends their awesome tank build, or sneaking into  hidden maps, or winning, or... you know, the opposite of winning ;)

Whatever  their reason, I added the disableSteamRichPresence setting in case  players want it to just say regular old "Cogmind" like it always has!

Comments

No comments found for this post.