Trying to write a derivation for a game

I’ve been playing Tibia for a few weeks on NixOS. I made it work by manually linking all needed libraries through LD_LIBRARY_PATH=.. ./client. Until a week ago. An update came out from the game and something changed. I cannot play anymore ;’(.

To play Tibia you need to download a launcher from their website which fetches the latest files for you and stores it into ~/.local/share/Cipsoft/Tibia/<some folder>. There it has a bin/client file somewhere which assumes you have a standard linux filetree, so obviously, that doesn’t work.

To run the launcher I’ve written a small derivation (couldn’t have done it without the help of my dear colleague @c0deaddict).

Now I’m using the files that the launcher downloads + stores as an input for another nix derivation, and it appears to be ‘working’. (no missing dependencies whatsoever)

with import <nixpkgs> {};

# url 1 (assets)   https://static.tibia.com/launcher/assets-current/assets.json
# url 2 (binaries) https://static.tibia.com/launcher/tibiaclient-linux-current/package.json

let 
  version = "23150";
  assets = ./Tibia/assets;
  binaries = ./Tibia/bin;
  src = ./Tibia/bin/client;
in

stdenv.mkDerivation rec {
  name = "tibia";
  system = "x86_64-linux";
  inherit src version;

  # Required for compilation
  nativeBuildInputs = [
    autoPatchelfHook # Automatically setup the loader, and do the magic
    makeWrapper
  ];

  # Required at runtime
  buildInputs = [
    stdenv.cc.cc
    glibc
    qt5.qtbase
    qt5.wrapQtAppsHook
    krb5
    e2fsprogs
  ];
  
  LD_LIBRARY_PATH = buildInputs; # lib.strings.makeLibraryPath 

  dontUnpack = true;
  installPhase = ''
    mkdir -p $out
    mkdir -p $out/bin
    mkdir -p $out/assets
    cp -R ${assets}/* $out/assets
    cp -R ${binaries}/* $out/bin
    rm $out/bin/client
    cp $src $out/bin/client
    ldd $out/bin/client
  '';

  postFixup = ''
    wrapQtApp $out/bin/client
  '';
}

It gives an neat result symlink thingy, which, when I try to run the client, gives:

➜ ./result/bin/client
Tibia could not save your configuration:
I/O error on file /nix/store/7gylhzcrr6gd2385dqylcnkrgxaa34ld-tibia/conf/clientoptions.json: No such file or directory
terminate called after throwing an instance of 'std::runtime_error'
  what():  Failed to create folder.
[1]    6996 abort      ./result/bin/client

Which makes sense, because I guess everything in the /nix/store needs to be read-only to be trustworthy and reproducible.

However, I’m not sure how I should proceed from this point. Is there a way I can configure a folder where Tibia can create/modify/delete whatever it wants?

2 Likes

It may depend on what the script does. Maybe the clientoptions has settings for those directories that you could change. There could be env variables you could set as well. It really depends on how configurable the application is.

You could use libredirect to divert some of the paths to something like XDG directories. Alternatively, you could also write your own preloader and patchelf that in (patchelf --add-needed).

If you’re looking for examples on patching up games with a certain degree of stubbornness: