Beyond All Reason launcher

No idea if anyone here is interested in this, or whether this is even the right place to post, but I had some fun last weekend :robot:

I recently discovered Beyond All Reason, a modern RTS game build on the popular open-source Spring game engine.

They do offer Linux versions of the launcher in form of AppImage and Flatpak, which would probably have worked. (I did not try)
But I wanted to know if I could write a nix derivation myself. So i did.

This is just the launcher, not the engine. (Although, Spring is already in nixpkgs, so that might not be much harder.)

All necessary resources are on GitHub under the beyond-all-reason organization.

Ingame lobby: GitHub - beyond-all-reason/BYAR-Chobby
Launcher: GitHub - beyond-all-reason/spring-launcher: Launcher for SpringRTS games
Downloader: GitHub - beyond-all-reason/pr-downloader: console downloader for spring maps/games written in c++

The launcher will download the engine and the game to ~/Beyond All Reason/.
I wrapped the result in steam-run, so that the game starts without further patching. The launcher itself is just an Electron app and does not require it.

{ lib
, stdenv
, fetchFromGitHub
, buildNpmPackage
, runCommand
, nodejs
, electron
, butler
, steam-run
, jq
, xorg
, libcxx

  # dependencies for pr-downloader
, gcc
, cmake
, curl
, pkg-config
, jsoncpp
, boost
, minizip
}:

# This builds the launcher for Beyond All Reason.
# Which can then download the engine, the lobby, and the game.
# Starts the launcher with steam-run, so that the game starts without further
# patching.

let
  version = "1.1861.0";
  srcs = {
    # Contains the configuration for the launcher.
    byar-chobby = fetchFromGitHub {
      owner = "beyond-all-reason";
      repo = "BYAR-Chobby";
      rev = "v${version}";
      sha256 = "sha256-YnOW63Z8A/W89TeeMDJcVKjA1ErATvPHzm26wQdWH2I=";
    };
    spring-launcher = fetchFromGitHub {
      owner = "beyond-all-reason";
      repo = "spring-launcher";
      rev = "439a9b7b7d835691267ad13586d0efc763d39b60";
      sha256 = "sha256-26bDjlbh2lppMC6+6pyqdaSNbVrwKPj4ckMK0LZleQY=";
    };
  };

  # From: https://github.com/beyond-all-reason/BYAR-Chobby/blob/1ee341043b6bb1f488ed5aab5d02c85018c572ed/.github/workflows/launcher.yml
  src = runCommand "byar-launcher-src-${version}"
    {
      buildInputs = [ nodejs jq ];
    } ''
    cp -r ${srcs.byar-chobby} BYAR-Chobby
    cp -r ${srcs.spring-launcher} launcher
    chmod -R +w *

    echo --- Patch launcher with dist_cfg
    cp -r BYAR-Chobby/dist_cfg/* launcher/src/
    for dir in bin files build; do
      mkdir -p launcher/$dir
      if [ -d launcher/src/$dir/ ]; then
        mv launcher/src/$dir/* launcher/$dir/
        rm -rf launcher/src/$dir
      fi
    done

    echo --- Make package.json
    GITHUB_REPOSITORY=beyond-all-reason/BYAR-Chobby
    cd BYAR-Chobby
    export PACKAGE_VERSION=${version}
    echo "Making build for version: $PACKAGE_VERSION"
    node build/make_package_json.js ../launcher/package.json dist_cfg/config.json $GITHUB_REPOSITORY $PACKAGE_VERSION
    cd ..

    echo --- Patching package.json
    # Rebuilding electron would fail: It tries to access github.com.
    # And we do not need it anyway.
    jq 'del(.devDependencies.electron)' launcher/package.json > temp
    mv temp launcher/package.json
    jq 'del(.packages."".devDependencies.electron)' launcher/package-lock.json \
      | jq 'del(.packages."node_modules/electron")' > temp
    mv temp launcher/package-lock.json

    echo --- Force dev mode to prevent launcher-update
    sed -i 's/const isDev = .*\;/const isDev = true\;/' launcher/src/launcher_wizard.js

    mv launcher $out
  '';

  nodeModules = buildNpmPackage {
    inherit src version;
    pname = "byar-launcher-package";
    npmDepsHash = "sha256-cCUtkycZ0bpLwcCfBjf+rTeoMHN7jIxcYCtyrB4rC8A=";
    npmFlags = [ "--legacy-peer-deps" ];
    dontNpmBuild = true;
    passthru = {
      buildInputs = [
        nodejs
        libcxx
        xorg.libX11
      ];
    };
    installPhase = ''
      mv node_modules $out
    '';
  };

  pr-downloader = stdenv.mkDerivation rec {
    pname = "pr-downloader";
    version = "master";
    src = fetchFromGitHub {
      owner = "beyond-all-reason";
      repo = "pr-downloader";
      rev = "79b605d013a0c5a92090b3892e8e0c0aeccac2a8";
      sha256 = "sha256-noroFiv2wAUCgI1ne2sP0PVBxIf20D+m5oa5+pk2OXQ=";
      fetchSubmodules = true;
    };
    buildInputs = [
      gcc
      cmake
      curl
      pkg-config
      jsoncpp
      boost
      minizip
    ];
    postInstall = ''
      mkdir $out/bin
      mv $out/pr-downloader $out/bin
    '';
  };
in
stdenv.mkDerivation {
  inherit src version;
  pname = "byar-launcher";
  phases = [ "buildPhase" ];
  buildPhase = ''
    mkdir -p $out/lib/dist
    cp -r $src/* $out/lib/dist
    chmod -R +w $out/lib/dist

    cp -r ${nodeModules} $out/lib/dist/node_modules

    rm $out/lib/dist/bin/butler/linux/butler
    ln -s ${butler}/bin/butler $out/lib/dist/bin/butler/linux/butler

    rm $out/lib/dist/bin/pr-downloader
    ln -s ${pr-downloader}/bin/pr-downloader $out/lib/dist/bin/pr-downloader

    mkdir -p $out/bin
    echo '#!/bin/sh' > $out/bin/byar-launcher
    echo "${steam-run}/bin/steam-run ${electron}/bin/electron $out/lib/dist" >> $out/bin/byar-launcher
    chmod +x $out/bin/byar-launcher
  '';
}

At some point in the future it could be nice to have the launcher as part of nixpkgs, but currently there is still a lot of development (and most importantly renaming) happening, so that would probably be wasted effort.
Anyway, a Steam release is planned

(I did not test multiplayer, but I see no reason why it would not work.)

3 Likes

Hello, I’ve tried appimage, flatpack, none of them are worked… The only reason I have windows is this game. I’ve recently switched from arch to nixos.