Compiling Barotrauma from Source

On Arch Linux for Linux

Barotrauma is a 2D co-op survival game about navigating the depths of the Jupiter’s moon Europa in a submarine. With the help of other players or NPCs, you need to operate the submarine, maintain the onboard systems, repair leaks, fight the local fish, take care of the crew and stay alive. It’s sold on Steam and runs on Linux. What’s better, its source code is available on GitHub for modders and limited joint development. Here’s a guide on how to compile Barotrauma on Linux for Linux.

In-game screenshot.

While the source for the game is publicly available, its graphical and other assets are not. To get a playable game at the end, you’ll need to purchase Barotrauma on Steam both for its Content directory containing its assets and multiplayer, which depends on Steam’s match-making. Compiling from source as-is won’t net you a DRM-free game. If that’s your goal, you’ll have to figure it out yourself, something the developer warns against in their end-user license agreement.

That out of the way, let’s begin.

Setup

These instructions are written for compiling Barotrauma for Linux on Arch Linux. However, I suspect they’ll apply equally well to other platforms, as beyond a few package mentions, there’s nothing specific to Arch Linux. You’re going to need some familiarity with the command line and developer tools. Nothing you couldn’t learn now.

First, ensure you’ve got Git installed.

pacman -S git

Then, let’s clone the Barotrauma’s repository from Github. To save disk space, let’s do a shallow clone that skips the history and just grabs the latest state. As of May 17, 2020, that’ll be ce4ccd9, which corresponds to v0.9.9.1. In total, 138.3 MiB.

git clone --depth 1 https://github.com/Regalis11/Barotrauma.git

The game’s written in C# using the .NET Core framework. We’ll need its SDK installed to run the build scripts and compile the game. Arch Linux has .NET Core available in its official repositories, making the installation easy. Barotrauma’s README mentions .NET Core v3.0, but v3.1 seems to work fine.

pacman -S dotnet-sdk

The rest of the game’s dependencies will either be installed by the .NET Core dotnet executable or are committed to the source repository as binary files. If I were you, I’d also now prepare an unprivileged user account or some other sandboxing to run the build under. After all, you’ll be running a lot of unaudited code off the Internet. One relatively convenient sandbox utility on Linux is Firejail (Firejail on Arch Wiki).

Compiling

The primary building and packaging happens via dotnet, a build tool that came with the .NET Core SDK. To get the Barotrauma Linux client to successfully compile, though, we’ll need to download a missing controller mapping file and apply a patch to skip copying already bundled dependencies.

SDL Game Controller Mappings

For some reason the build depends, but doesn’t automatically download, the game controller mapping database for SDL from SDL_GameControllerDB. Let’s do so ourselves.

mkdir -p Libraries/MonoGame.Framework/Src/ThirdParty/SDL_GameControllerDB
wget https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt -O Libraries/MonoGame.Framework/Src/ThirdParty/SDL_GameControllerDB/gamecontrollerdb.txt

Those that try to run the dotnet publish command from below before downloading the controller configuration file, will encounter the following error:

CSC : error CS1566: Error reading resource 'gamecontrollerdb.txt' -- 'Could not find a part of the path '/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/SDL_GameControllerDB/gamecontrollerdb.txt'.' [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]

Skipping Compiling Bundled Dependencies

As can be guessed from its use of the SDL game controller database, Barotrauma depends on SDL. It also depends on OpenAL for audio. Actually, Barotrauma depends on the MonoGame framework, which is what seems to depend on both. Nonetheless, MonoGame seems to insist on having access to SDL’s and OpenAL’s dynamic libraries for all three platforms — Windows, Linux and Mac — during its build. Fortunately for us, Barotrauma’s developers have included compiled versions of the former in the repository. As MonoGame is still looking for them in the ThirdParty directory, though, we’ll need to patch the build project in Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj to not do so.

Copy the diff below to a file or just download the patch directly.

diff --git a/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj b/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj
index 7ef537f..63c1b2a 100644
--- a/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj
+++ b/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj
@@ -511,64 +511,6 @@
     </Compile>
   </ItemGroup>
 
-  <ItemGroup>
-    <None Include="..\ThirdParty\Dependencies\MonoGame.Framework.dll.config">
-      <Platforms>WindowsGL,Linux,MacOS</Platforms>
-      <Link>MonoGame.Framework.dll.config</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\SDL\Windows\x86\SDL2.dll">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x86\SDL2.dll</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\SDL\Windows\x64\SDL2.dll">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x64\SDL2.dll</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\openal-soft\Windows\x86\soft_oal.dll">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x86\soft_oal.dll</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\openal-soft\Windows\x64\soft_oal.dll">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x64\soft_oal.dll</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\SDL\Linux\x86\libSDL2-2.0.so.0">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x86\libSDL2-2.0.so.0</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\SDL\Linux\x64\libSDL2-2.0.so.0">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x64\libSDL2-2.0.so.0</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\openal-soft\Linux\x86\libopenal.so.1">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x86\libopenal.so.1</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\openal-soft\Linux\x64\libopenal.so.1">
-      <Platforms>WindowsGL,Linux</Platforms>
-      <Link>x64\libopenal.so.1</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\SDL\MacOS\Universal\libSDL2-2.0.0.dylib">
-      <Platforms>WindowsGL,Linux,MacOS</Platforms>
-      <Link>libSDL2-2.0.0.dylib</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-    <None Include="..\ThirdParty\Dependencies\openal-soft\MacOS\Universal\libopenal.1.dylib">
-      <Platforms>WindowsGL,Linux,MacOS</Platforms>
-      <Link>libopenal.1.dylib</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
-  </ItemGroup>
-
   <ItemGroup>
     <EmbeddedResource Include="MonoGame.bmp">
       <LogicalName>MonoGame.bmp</LogicalName>

Then navigate to the source directory and pass the patch to the patch executable. In case you’re missing patch, install it via Pacman (pacman -S patch).

patch -p1 < monogame-ce4ccd9.patch

You could verify the patch applied correctly by checking Git.

$ git status --short
 M Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj

Skipping patching the MonoGame build project before attempting to build Barotrauma results in the following errors referencing DLLs from Windows, Linux and Mac, even if you’re building only for a Linux system.

Barotrauma’s MonoGame compile errors
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/MonoGame.Framework.dll.config" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/SDL/Linux/x64/libSDL2-2.0.so.0" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/SDL/Linux/x86/libSDL2-2.0.so.0" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/SDL/MacOS/Universal/libSDL2-2.0.0.dylib" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/SDL/Windows/x64/SDL2.dll" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/SDL/Windows/x86/SDL2.dll" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/openal-soft/Linux/x64/libopenal.so.1" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/openal-soft/Linux/x86/libopenal.so.1" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/openal-soft/MacOS/Universal/libopenal.1.dylib" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/openal-soft/Windows/x64/soft_oal.dll" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]
/usr/share/dotnet/sdk/3.1.103/Microsoft.Common.CurrentVersion.targets(4570,5): error MSB3030: Could not copy the file "/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/ThirdParty/Dependencies/openal-soft/Windows/x86/soft_oal.dll" because it was not found. [/home/user/Barotrauma/Libraries/MonoGame.Framework/Src/MonoGame.Framework/MonoGame.Framework.Linux.NetStandard.csproj]

Compiling the Game

With the SDL game controller database downloaded and MonoGame’s build project patched, we’re ready to build Barotrauma. For that, we’ll run dotnet publish and pass it the project file for the Linux game:

dotnet publish Barotrauma/BarotraumaClient/LinuxClient.csproj --configuration Release --self-contained --runtime linux-x64 /p:Platform=x64 /p:DebugType=None --output game

Depending on the performance of your computer, this should take 10–20 seconds. You’ll find the executable files for the game in the game directory (as requested by --output game). As of May 17, 2020, it generates around 133.2 MiB worth of files. All that’s missing now are the graphical, audio and other assets. Locate the game’s directory in your Steam library and copy the Content directory over to game. The only conflicts you should see are *.xnb files in Content/Effects. Skip overwriting those.

That’s it. Copy the game directory where you see fit and run the Barotrauma executable.

./Barotrauma

Your game preferences are in the config_player.xml file in the game directory. If you wish to restore your video and control preferences, copy it from Steam, too. The config_player.xml file is worth taking a look also for disabling the splash screen, analytics reporting and possible other tweaks. Barotrauma’s saves are in ~/.local/share/Daedalic Entertainment GmbH/Barotrauma, so those should be available wherever you put the compiled game.

By the way, should the command line invocation above not work by the time you’re reading this, you could also review the Deploy/Linux directory in the repository. It includes the scripts the game authors use for compiling.

Compiling the Server

If you intend to host a server with your compiled version, you’ll also need to compile the server executable. Using the same dotnet publish invocation as before, replace Client with Server:

dotnet publish Barotrauma/BarotraumaServer/LinuxServer.csproj --configuration Release --self-contained --runtime linux-x64 /p:Platform=x64 /p:DebugType=None --output game

This adds the DedicatedServer executable (along with a DLL) to the game output folder.

Build Options

The dotnet build system takes a number of options. For the sake of reference, here are the options used above as described by dotnet publish --help:

Option Description
--configuration The configuration to publish for. The default for most projects is ‘Debug’.
--self-contained Publish the .NET Core runtime with your application so the runtime doesn’t need to be installed on the target machine.
--runtime The target runtime to publish for. This is used when creating a self-contained deployment.
/p:DebugType=None Skips generating and copying over debug symbol files (*.pdb).

If you’re playing on the same machine you compiled on (and have .NET Core installed), you could save a bit of disk space by not bundling the .NET Core libraries in the game output folder. Pass --no-self-contained to dotnet to reduce the game directory to 55.2 MiB. I think it’s safer to keep them bundled, should you want to copy the game over to another computer or just uninstall the dotnet-sdk package previously installed.