Skip to content

Instantly share code, notes, and snippets.

@TrueBrain
Last active March 26, 2023 14:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TrueBrain/bccb44cf813cb556613dcb89889bd357 to your computer and use it in GitHub Desktop.
Save TrueBrain/bccb44cf813cb556613dcb89889bd357 to your computer and use it in GitHub Desktop.
Steam / Discord integration (Rich Presence)

To start with, few things to keep in mind:

  • I am not a lawyer.
  • Neither are you.
  • 1000 people 1000 opinions; this is not so much about opinions, but about facts, options, and risk.
  • I did a morning of searching the web to gather this information, just so we have something to talk about. To bring this a bit more into facts rather than opinions we all have on what GPL is and isn't :D

Problem description

With us going to Steam, the request for Steam integration has increased. For a long while now, we have requests to integrate with Discord. Although Discord does have an SDK variant that is MIT licenses, for the shake of this conversation we assume we want to integrate with the latest, non-free, variant. Steamworks SDK is non-free either.

The problem we face with such integration, is that as GPL software you cannot just include non-free software: https://www.gnu.org/licenses/gpl-faq.html#GPLPlugins . Basically, only if you call main in such plugin, or use fork/exec with very limited data-sharing, FSF says no.

Important to note here: this is an opinion by the FSF. The whole GPL hasn't really seen court yet, and lawyers tend to disagree with what FSF thinks it means. That is to say: FSF is much more strict about everything. Basically they say: anything GPL software uses, dynamically, statically, etc etc, should be GPL too. This is a very optimistic look on the world, but far from the reality.

So, the question that we set out: can we integrate with Steam / Discord and do we want to.

The breakdown

To answer that question, we need to do some ground work.

GPL and plugins

First, https://www.gnu.org/licenses/gpl-faq.html#GPLPlugins does allow some room to simply link to a non-free library; does that apply in our case? As if that would be the case, we would be done rather quick.

Sadly, this does not seem to be the case. Mostly, for both Discord and Steam, using their network infrastructure would greatly help multiplayer. But this is neither just calling a main, and arguing that it is non-"intimate communication" might also be a hard claim.

That said, this is of course up for debate.

dlopen()

There is a strong disagreement if for example using dlopen prevent the license clause, as it is not "linking against". There is said to be a common acceptance that the license makes no difference between static vs dynamic linking, or "compile time" vs "runtime". https://www.gnu.org/licenses/gpl-faq.en.html#MereAggregation writes a bit about this. The explanation here is that both result in the binary being tightly coupled, and as such a derivitate work of both. Given one is GPL and the other is non-free, this is not compatible, and as such a license violation.

A very nice read about this can be found here: https://lwn.net/Articles/548216/

Basically, lawyers argue: well, no, dynamic linking is done by the user, not the one publishing. So as long as the user doesn't distribute it, that is fine.

Using an API and shims

The common answer to this problem is: use a shim! With the idea that it magically fixes all problems ;)

API in this scenario is either a code-wise interface or an exec/fork interface or a network interface.

The reality seems a bit more complex. Most close in the GNU FAQ is this entry: https://www.gnu.org/licenses/gpl-faq.html#LinkingOverControlledInterface It basically says: if you define an API and you allow the license to include non-free software, that is fine. FSF doesn't like it, but it is fine.

The main issue for OpenTTD here is, who can make this exception. Normally the answer is: the copyright holders. There is a bit of a nuance here: the ones of writing the code, or the complete product?

Also here a difference between allowing integration and distribution starts to appear. Best worded by GStreamer: https://gstreamer.freedesktop.org/documentation/frequently-asked-questions/legal.html?gi-language=c

You may not distribute the plug-in with the GPL application. Distributing the plug-in alone, with the knowledge that it will be used primarily by GPL software is a bit of an edge case. We will not advise you that it would be safe to do so, but we also will not advise you that it would be absolutely forbidden

Basically, the argument goes: if you know the intend of the plugin is to allow non-free software, that is a violation of the license.

Other projects had to deal with all of this too, of course. One of the best comments about this I found: https://lwn.net/Articles/548576/

Exactly this case came up in a controversy over use of the GPL2-licensed GMP library by code (RSAREF) with an incompatible license. Someone then produced a BSD-licensed library called FGMP, that provided the same interface but was not as good. RMS agreed that the FSF no longer had an objection to RSAREF, even though in practice no one actually used FGMP. Its existence alone meant that the FSF could no longer argue that RSAREF was effectively a derivative work of GMP via the user-does-the-link trick (originally the program would not work without GMP).

NewGRFs / AIs / GSes

Besides Rich Presence, we also have to be honest about other integration we do. We allow NewGRFs / AIs / GSes to be of any license, even non-free. We load them in the game and process them. We do not explicitly mention this allowed way of working in our license.

Is this a violation of GPL?

As this has never been raised, one can assume we all implicitly agree that this is allowed by our license. This is not much different from integration with Steam / Discord if done via a similar API as NewGRFs / AIs / GSes.

Who cares about violations?

Basically, anyone "who holds copyright on a substantial part of the code can enforce the GPL" can challenge this. (https://www.gnu.org/licenses/gpl-faq.html#NonfreeDriverKernelLinux)

This means, people with 10 lines of code, cannot. So legally, the only ones we are arguing with are those who made substantial contributions to OpenTTD. Those are the only ones who care about violations.

That said, there is also the social aspect. What does the wider audiance accept: when do they no longer consider you non-free. In concensus, this seems to boil down to: as long as it is 100% fully optional, and it doesn't allow anything you couldn't do otherwise, OpenTTD is still free.

To put it more bluntly:

  • Steam Workshop: no
  • Steam Networking: yes

Possibly solutions

Given all the problems surrounding this (and yes, I know there are many), we can deduce possible solutions. In basic, as with everything in life, it comes down to: how much risk do we accept.

dlopen() with Steamworks SDK

Just ignore it is a clear violation of GPL, and do it anyway. Not having the Steamworks DLL (which is required for this to work), means you don't have Steam integration. Having it, means it does work.

This is the most naive approach of them all, and it is best said in words of Steam itself: https://partner.steamgames.com/doc/sdk/uploading/distributing_opensource

Basically, they say: no, this is not allowed by GPL, and by distributing the game like that you are in violation. This means anyone "who holds copyright on a substantial part of the code can enforce the GPL" can challenge Steam that it is not okay.

Use an API (Rich Presence API)

This seems to be the most generally accepted course of action. ffmpeg, GStreamer, VLC, ... many use this approach. The API is meant for free and non-free plugins alike.

The only catch: by FSF reasoning, if you distribute both OpenTTD and, say, the Steamworks DLL, you are still in violation of the license, as the derivitive work is not GPL (see earlier).

This means the problem shifts from a coding issue to a distribution issue.

It also means, both Steam and Discord need to get a shim to talk to this API, which is non-GPL licenses, and created by us. So basically, we would need to make non-GPL (possibly non-free) software to make this work.

Owh, and at least 1 GPL example library :P

Don't integrate

Always a possibility! One could argue only why NewGRFs / AIs / GSes would be allowed in that case .. ;)

Possibly approaches

Assuming we are not going for dlopen() and do want to do it, to my best knowledge, the API is the way to go.

This leaves us with a few choices:

  1. the GNU GPL suggestion is to add a condition to the API licensing, to allow non-free. This would resolve the distribution part. The problem is: does that require the copyright holder of all of OpenTTD to sign off on this, or only those building the API?
  2. do we say, given NewGRFs / AIs / GSes allow a similar structure, this can be extended to a rich presence, and nothing changes?
  3. do we need concensus on this with the current developers, or with all contributors?

Additionally, we have to balance if the public is okay with us doing this. There will be purist around there, that will be like: omg, you are not strictly free anymore, and as such, non-free! That argument can be made, how-ever silly given the background of OpenTTD and the fact we have NewGRFs / AIs / GSes. Nevertheless, it is valid.

Distribution

Steam depots

How Steam works, is that distribution happens in depots. For example, currently there are 7 depots:

  • Win32
  • Win64
  • Linux
  • MacOS
  • OpenGFX
  • OpenSFX
  • OpenMSX

One could add a depoy "Steamwork SDK" DLL/so. This would mean, strictly seen, that we do not distribute a combination of OpenTTD and Steamwork SDK. This is really splitting hairs, I am fully aware.

Manual download

Offer the plugins as separate downloads on our site. Means the user has to do the work.

Integrate in installers

Well, we only have NSIS for Windows, but integrate it in there, and download the binaries separately. But again, splitting hairs. We are giving the user something we know is against the spirit FSF has for GPL.

Allow downloading via BaNaNaS

Similar as other NewGRFs / AIs / GSes, make a new category "Rich Precense". Also easier allows us to update it etc, so there are even some benefits of going this approach.

The only catch is that we currently don't do executable binary distribution via BaNaNaS, so some limitations have to apply (like: only developers can upload those, and only if the are preannounced via a Pull Request, for example).

@andythenorth
Copy link

Good write up of tricky issue, thanks.

@nielsmh
Copy link

nielsmh commented Apr 5, 2021

I wrote a proof of concept Discord integration by dynamically loaded plugin a while ago.

Patch (not currently maintained): https://github.com/nielsmh/OpenTTD/tree/rich-presence
Plugin: https://github.com/nielsmh/ottd-discord

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment