Placing and moving files from a ZIP into user directory

Hi all,

I’m struggling to install SMAPI from source which is a modding API for a game called Stardew Valley using NixOS and Home manager.

The source is a zip file from Release 4.2.1 · Pathoschild/SMAPI · GitHub.

I’m trying to install it using the manual installation steps as I assume that allows the installation to be more declarative compared to running an script? After looking around, it seems like I need to make a derivation which is what I attempted but I don’t quite understand how to move the files from the unzipped Github release to the location of the game in my user’s directory.

According to the README of SMAPI, I need to reproduce the following steps using Nix and Home Manager:

  1. Unzip “internal/unix/install.dat”. You can change ‘.dat’ to ‘.zip’, it’s just a normal zip file renamed to prevent
    confusion.

  2. Copy the files from the folder you just unzipped into your game folder. The
    StardewModdingAPI.exe file should be right next to the game’s executable.

  3. Copy Stardew Valley.deps.json in the game folder, and rename the copy to
    StardewModdingAPI.deps.json.

  4. rename the “StardewValley” file (no extension) to “StardewValley-original”, and
    “StardewModdingAPI” (no extension) to “StardewValley”. Now just launch the game as usual to
    play with mods.

So far, I’ve got this in my configuration:

# smapi.nix
{ pkgs, stdenv }:
stdenv.mkDerivation rec {
  pname = "SMAPI";
  version = "4.2.1";

  src = pkgs.fetchzip {
    url = "https://github.com/Pathoschild/${pname}/releases/download/${version}/${pname}-${version}-installer.zip";
    hash = "sha256-8fIwAZI9obCUfQcrGuNlq84st7iIQ/8Hfrgkeqsk/3c=";
  };

  nativeBuildInputs = with pkgs; [ unzip ];

  unpackPhase = ''
    runHook preUnpack
    mkdir -p $out/bin
    cp -r ${src}/* $out/
    ${pkgs.unzip}/bin/unzip -o ${src}/internal/linux/install.dat -d $out
    runHook postUnpack
  '';

  installPhase =
    let
      gamePath = "~/.local/share/Steam/steamapps/common/Stardew\\ Valley/";
    in
    ''
      runHook preInstall
      cp -a $out/. ${gamePath}
      cp ${gamePath}/Stardew\\ Valley.deps.json ${gamePath}/StardewModdingAPI.deps.json
      mv ${gamePath}/StardewValley ${gamePath}/StardewValley-original
      mv ${gamePath}/StardewModdingAPI ${gamePath}/StardewValley
      runHook postInstall
    '';

}

Obviously this is wrong but I’m not sure how to progress after step 1. I also don’t know how to use the derivation to actually “install” SMAPI.

Any help is appreciated :slight_smile:

Yeah, so that’s practically impossible to do “declaratively”. You’re fundamentally trying to munge files that were installed imperatively in the first place. Nix has no control over your stardew valley installation, and should not, because it’s impossible for nix to know anything about it.

The “correct” way from an idiomatic point of view would be to include this in your stardew valley derivation, i.e., installing stardew valley with nix too. But that’s likely all but impossible.

Your only real option is to write a script which installs your files and then starts stardew valley, and use that to launch the game. If you add that script to your PATH with home-manager you can use nix to substitute the mod file location, and thereby loop it into nix; writing such a script that actually covers all the edge cases will be quite a bit of work, though.

2 Likes

Hey TLATER, that does sound like too much effort for little benefit. I guess I’ll just install it imperatively.

Thanks for your kind reply, you’ve taught me a little bit more about Nix :blush:

For the record, a naive implementation would look something like this: dotfiles/pkgs/packages/edopro/edopro.nix at master · TLATER/dotfiles · GitHub

That’s far from “good”, though. Many edge cases that could break stuff catastrophically when the package updates. Eventually I’ll think about how assets work and clean it up properly…

Unfortunately someone else merged an old version of that script of mine into nixpkgs (with no attribution either), and now everyone else’s installations will probably break one day. Shows me for putting half-assed work out there ;p