Skip to content

Commit

Permalink
starsector: add packaging infrastructure for parsing mod files
Browse files Browse the repository at this point in the history
This adds a the mkStarsectorMod helper function. It can produce
Starsector mod packages that are then passed to linkFarm to be
processed by the game.

Signed-off-by: Fernando Rodrigues <[email protected]>
  • Loading branch information
SigmaSquadron committed Oct 29, 2024
1 parent 5de106a commit fedc2f1
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 1 deletion.
110 changes: 110 additions & 0 deletions pkgs/by-name/st/starsector/mods.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
lib,
stdenvNoCC,
fetchzip,
runCommand,
unrar,
starsector,
jq,
dos2unix,
}:

let
semiOptionalInput =
input: bool:
"mkStarsectorMod needs an '${input}' attribute, or 'isStandardSrc' set to '${toString bool}'.";
mkStarsectorMod =
{
pname,
version,
isStandardSrc ? true,
src ? if isStandardSrc then "" else throw semiOptionalInput "src" true,
url ? if !isStandardSrc then "" else throw semiOptionalInput "url" false,
hash ? if !isStandardSrc then "" else throw semiOptionalInput "hash" false,
author ? "",
prettyName ? "",
summary ? "",
description ? "",
forumURL ? "",
}:

stdenvNoCC.mkDerivation (finalAttrs: {
inherit version pname;

src =
if isStandardSrc then
fetchzip {
inherit url hash;
nativeBuildInputs = lib.optional (lib.hasSuffix ".rar" url) unrar;
postFetch = ''
if test -e "$out"/mod_info.json; then
return 0; else
results="$(find $out -type d -exec test -e '{}'/mod_info.json \; -print)"
if [ "$(echo "$results" | wc -l)" = 1 ]; then
mv "$results"/* . && rm -rf "$results"; else;
echo "Starsector mod: '${pname}' has more than one mod_info.json." && exit 1
fi
fi
'';
}
else
src;

dontConfigure = true;
dontBuild = true;

installPhase = "mkdir $out && cp -prvd * $out";

passthru = {
inherit author prettyName forumURL;
tests = {
gameVersionMatches =
runCommand "${finalAttrs.pname}-gameVersionMatchTest"
{
nativeBuildInputs = [
jq
dos2unix
];
}
''
dos2unix ${finalAttrs.finalPackage}/mod_info.json
modVersion="$(jq -n -f ${finalAttrs.finalPackage}/mod_info.json | jq -cMj .gameVersion)"
gameVersion="${starsector.version}"
if [ "$gameVersion" = "$modVersion" ]; then
echo "Mod version matches!" && echo "Success: ${finalAttrs.pname}" >> $out
else
echo "Mod version did not match! Tried comparing '$gameVersion' to '$modVersion'."
exit 1
fi
'';
};
};

meta = {
description = "Starsector Mod: ${prettyName}";
longDescription =
(if (lib.hasPrefix summary description) then description else "${summary}\n${description}")
+ "\n- by ${author}.";
homepage = forumURL;
sourceProvenance = lib.optional (lib.pathIsDirectory (
finalAttrs.src + /jars
)) lib.sourceTypes.binaryBytecode;
inherit (starsector.meta)
license
maintainers
platforms
badPlatforms
;
};
});
in
{
inherit mkStarsectorMod;
}

# TODO: Somehow parse the very non-standard mess that are
# Starsector mods. There are mod packages that include two mods
# in a single zip, some mods just straight up use invalid JSON,
# while others can only be accessed through impermanent source
# directories and/or lack a versioned URL. Oh, did I mention the
# lack of consistent line endings?
47 changes: 46 additions & 1 deletion pkgs/by-name/st/starsector/package.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
lib,
callPackage,
linkFarmFromDrvs,
fetchzip,
libGL,
makeWrapper,
Expand All @@ -13,10 +15,24 @@
curl,
gnugrep,
common-updater-scripts,

starsectorMods ? [ ],
}:

assert lib.assertMsg (
builtins.isList starsectorMods
&& builtins.all (x: x) (
map (n: lib.isDerivation (builtins.elemAt starsectorMods n)) (
lib.range 0 ((builtins.length starsectorMods) - 1)
)
)
) "The definition for 'starsectorMods' is not of type 'list of derivation'.";

let
openjdk = openjdk8;

mkStarsectorMod = lib.recurseIntoAttrs (callPackage ./mods.nix { });
mergedModPath = linkFarmFromDrvs "mergedModPath" starsectorMods;
in

stdenv.mkDerivation (finalAttrs: {
Expand Down Expand Up @@ -90,7 +106,11 @@ stdenv.mkDerivation (finalAttrs: {
--replace-fail "./jre_linux/bin/java" "${openjdk}/bin/java" \
--replace-fail "./native/linux" "$out/share/starsector/native/linux" \
''
# We also point the mod, screenshot, and save directories to $XDG_DATA_HOME.
# Set the mods folder to the merged store directory if we're using the mod plugins.
+ lib.optionalString (starsectorMods != [ ]) ''
--replace-fail "./mods" "${mergedModPath}" \
''
# We also point the mod (if `starsectorMods == [ ]`), screenshot, and save directories to $XDG_DATA_HOME.
+ ''
--replace-fail "=." "=\''${XDG_DATA_HOME:-\$HOME/.local/share}/starsector" \
''
Expand Down Expand Up @@ -120,10 +140,35 @@ stdenv.mkDerivation (finalAttrs: {
};
text = builtins.readFile ./update.sh;
};
inherit mkStarsectorMod;
};

meta = {
description = "Open-world, single-player space combat, roleplaying, exploration, and economic game";
longDescription = ''
Starsector can be extended with third-party modifications from the [Fractal Softworks Forum](https://fractalsoftworks.com/forum/index.php?&board=8.0).
By default, mods can be imperatively installed in `$HOME/.local/share/starsector/mods`, but you can also override the `starsector` derivation to install mods declaratively, like so:
```nix
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
(starsector.override {
starsectorMods = [
(starsector.mkStarsectorMod {
pname = "myFavouriteMod";
version = "1.0.0";
url = "https://somefilerepository.example/yourMod/modFile.zip";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
})
# ... more mod derivations.
];
})
];
}
```
This will create a merged store path with the specified mods, and Nix will handle fetching and installing.
**Note:** as the mods will be stored inside the read-only /nix/store, they will not be able to write files during runtime, which may cause game crashes if they attempt to do anyway.
'';
homepage = "https://fractalsoftworks.com";
downloadPage = finalAttrs.meta.homepage + "/preorder";
changelog = finalAttrs.meta.homepage + "/blog";
Expand Down

0 comments on commit fedc2f1

Please sign in to comment.