[Game] Configuring saves directory for Starsector

I tried to run starsector directly from nixpkgs, and it failed complaining about not being able to write its logfile, as in this issue. I’ve been trying to fix it, and I noticed that in the wrapped script it still used relative paths (i.e.: ./saves or ./starsector.log) which of course, it can’t open because they end up in the nix store.

So I’ve been trying to make them point to $XDG_HOME_DATA, as suggested in this other post. But I’ve had no luck because the variable doesn’t seem to be initialized. I have this so far:

  installPhase = ''
    runHook preInstall

    mkdir -p $out/bin
    rm -r jre_linux # remove jre7
    rm starfarer.api.zip
    cp -r ./* $out

    mkdir -p $out/share/icons/hicolor/64x64/apps
    ln -s $out/graphics/ui/s_icon64.png $out/share/icons/hicolor/64x64/apps/starsector.png

    wrapProgram $out/starsector.sh \
      --prefix PATH : ${lib.makeBinPath [ openjdk ]} \
      --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath buildInputs} \
      --run 'mkdir -p ''${XDG_DATA_HOME:-~/.local/share}/starsector' \
      --run 'mkdir -p ''${XDG_DATA_HOME:-~/.local/share}/starsector/saves' \
      --run 'mkdir -p ''${XDG_DATA_HOME:-~/.local/share}/starsector/screenshots' \
      --run 'mkdir -p ''${XDG_DATA_HOME:-~/.local/share}/starsector/mods' \
      --run 'mkdir -p ''${XDG_DATA_HOME:-~/.local/share}/starsector/logs' \
      --chdir "$out"
    ln -s $out/starsector.sh $out/bin/starsector

    runHook postInstall
  '';

  # it tries to run everything with relative paths, which makes it CWD dependent
  # also point mod, screenshot, and save directory to $XDG_DATA_HOME
  prePatch = ''
    substituteInPlace starsector.sh \
      --replace "./jre_linux/bin/java" "${openjdk}/bin/java" \
      --replace "./native/linux" "$out/native/linux" \
      --replace "./saves" "\$XDG_DATA_HOME/starsector/saves" \
      --replace "./mods" "\$XDG_DATA_HOME/starsector/mods" \
      --replace "paths.logs=." "paths.log=\$XDG_DATA_HOME/starsector/logs" \
      --replace "./screenshots" "\$XDG_DATA_HOME/starsector/screenshots"
  '';

If I try and replace the \$ with ''$ as I’ve seen on other nix expressions the resulting wrapped script just has nothing --I suspect the shell variable doesn’t exist–. I can get the game to run if I hardcode the path (/home/myuser/.local/share/) but I’m trying to fix it for everyone and submit a patch.

Is there any way I can refer to a writable path that makes sense in this situation? I thought of trying to refer to the user, but this package is supposed to also be installable from configuration.nix. Thanks for the help in advance.

I assume your using flakes? Many environment variables (all?) are cleared when evaluating flakes to ensure they are stateless. That being said, I’m surprised what you have isn’t working since the shell script should expand the environment variables at runtime. With how you have it now, does the resulting starsector.sh script have $XDG_DATA_HOME in it?

I’ve run into the same problem when trying to install a DBMS with a config file in “$out” and a log file whose path is absolute to that so there was no way around passing it a local path. The best I could do was create a wrapper function that accepted a path so that the path isn’t in the derivation itself but in the flake that calls it. If you’re placing this in home-manager you should have access to your home directory so in your home.packages list you would have something kind of like (starsectorWrapper { dataHome = "${homeDirectory}/.local/share)". You may even be able to get your data home with the xdg module in home-manager.