summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorseth <[email protected]>2023-09-19 00:28:30 -0400
committerseth <[email protected]>2023-09-19 01:09:34 -0400
commitf924887c4b646aa2ce762039070f8741ab933221 (patch)
treedb81ed2b866a6a00f7ddf13c8846c6a3b1f6018d /lib
parent1c9c0ef2e40fbd1a921b446d8fe5884e645e4308 (diff)
feat!: introduce fetchPackwizModpack
this is a major **breaking** change, replacing previous functions such as `mkPackwizPackages` & `mkModLinks`
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix180
-rw-r--r--lib/fetchPackwizModpack.nix136
-rw-r--r--lib/packwiz-installer-bootstrap.nix7
-rw-r--r--lib/packwiz-installer.nix7
4 files changed, 154 insertions, 176 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 8a6e7c1..f69ade0 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -1,178 +1,6 @@
-let
- inherit
- (builtins)
- attrNames
- concatStringsSep
- hashFile
- fetchurl
- fromJSON
- listToAttrs
- mapAttrs
- readDir
- readFile
- replaceStrings
- toFile
- toJSON
- ;
+final: prev: {
+ fetchPackwizModpack = final.callPackage ./fetchPackwizModpack.nix {};
- # loads data from a toml json given
- # the directory (dir) and filename (name)
- # string -> string -> attrset
- fromMod = dir: name: fromTOML (readFile "${dir}/${name}");
-
- # replaces `.pw.toml` extensions with `.jar`
- # to correct the store paths of jarfiles
- # string -> string
- fixupName = replaceStrings [".pw.toml"] [".jar"];
-
- # *pkgs*.fetchurl wrapper that downloads a
- # jarfile mod. pkgs.fetchurl is used over builtins
- # here since we have a checksum and can take advantage
- # of fixed output derivations
- # attrset -> string -> attrset -> store path
- mkMod = pkgs: name: mod:
- pkgs.fetchurl {
- name = fixupName name;
- inherit (mod) url sha256;
- };
-
- # maps each mod in our checksums.json format
- # to the store path of a fixed output derivation
- # attrset -> attrset
- genMods = pkgs:
- mapAttrs (mkMod pkgs);
-
- # this is probably what you're looking for if
- # you're a developer trying to use this in your modpack.
- # this is where you create a checksums file for end users
- # to put into mkPackwizPackages, so make sure you keep it up to
- # date!
- #
- # `dir` is a path to the folder containing your .pw.toml files
- # files for mods. make sure they are the only files in the folder
- #
- # path -> file
- mkChecksums = dir: let
- mods = readDir dir;
-
- getChecksum = name: url:
- hashFile "sha256" (fetchurl {
- name = fixupName name;
- inherit url;
- });
-
- toWrite =
- toJSON
- (mapAttrs (mod: _: let
- data = fromMod dir mod;
- in {
- inherit (data.download) url;
- sha256 = getChecksum mod data.download.url;
- })
- mods);
- in
- toFile "checksums-json" toWrite;
-
- # this is probably what you're looking for if
- # you're an end user trying to implement a modpack in
- # your module.
- #
- # `pkgs` is an instance of nixpkgs for your system,
- # must at least contain `fetchurl`.
- #
- # `checksums` is a json file from an upstream modpack
- # containing the names, urls, and sha256sums of mods
- #
- # attrset -> path -> attrset
- mkPackwizPackages = pkgs: checksums: genMods pkgs (fromJSON (readFile checksums));
-in {
- inherit mkChecksums mkPackwizPackages;
-
- # this another function modpack developers will be looking
- # for. it allows you to build a modpack compatible with MultiMC
- # and Prism Launcher, containing external files.
- #
- # `pkgs` is an instance of nixpkgs with at least lib, runCommand,
- # and zip
- #
- # `mods` is the result of mkPackwizPackages
- #
- # `filesDir` is the root path of all external files you want
- # included in your zipped modpack
- #
- # `name` is a string containing the name of your modpack
- mkMultiMCPack = {
- pkgs,
- mods,
- filesDir ? "",
- name,
- }: let
- inherit (pkgs) fetchurl lib runCommand zip;
- inherit (lib) forEach;
-
- packwiz-installer-bootstrap = fetchurl {
- url = "https://github.com/packwiz/packwiz-installer-bootstrap/releases/download/v0.0.3/packwiz-installer-bootstrap.jar";
- sha256 = "sha256-qPuyTcYEJ46X9GiOgtPZGjGLmO/AjV2/y8vKtkQ9EWw=";
- };
-
- forNames = attrset: forEach (attrNames attrset);
- commandSep = concatStringsSep "; ";
- modFiles = let
- commands = forNames mods (mod: "cp -r ${mods.${mod}} $out/decompressed/.minecraft/mods/");
- in
- commandSep commands;
-
- regularFiles =
- if filesDir != ""
- then
- (let
- files = readDir filesDir;
- commands = forNames files (file: "cp -r ${filesDir}/${file} $out/decompressed/");
- in
- commandSep commands)
- else "echo 'not copying external files...'";
- in
- runCommand name {} ''
- mkdir -p $out/decompressed/.minecraft/mods
- ${regularFiles}
- ${modFiles}
- cp ${packwiz-installer-bootstrap} $out/decompressed/.minecraft/packwiz-installer-bootstrap.jar
-
- cd $out/decompressed
- ${zip}/bin/zip -r ../${name}.zip {*,.*}
- '';
-
- # this creates an `apps` attribute for a flake
- # which runs a bash script to generate a checksums
- # file
- #
- # `pkgs` is an instance of nixpkgs for your system,
- # must at least contain `writeShellScriptBin`
- #
- # `dir` is a path to the folder containing your .pw.toml files
- # files for mods. make sure they are the only files in the folder
- #
- # attrset -> path -> attrset
- mkChecksumsApp = pkgs: dir: let
- inherit (pkgs) writeShellScriptBin;
- checksums = mkChecksums dir;
- name = "generate-checksums";
- script = writeShellScriptBin name ''
- cat ${checksums} > checksums.json
- '';
- in {
- type = "app";
- program = script.outPath + "/bin/${name}";
- };
-
- # this creates an attrset value for
- # minecraft-servers.servers.<server>.symlinks
- # attrset -> attrset
- mkModLinks = mods: let
- fixup = map (name: {
- name = "mods/" + fixupName name;
- value = mods.${name};
- }) (attrNames mods);
- in
- listToAttrs fixup;
+ packwiz-installer-bootstrap = prev.callPackage ./packwiz-installer-bootstrap.nix {};
+ packwiz-installer = prev.callPackage ./packwiz-installer.nix {};
}
diff --git a/lib/fetchPackwizModpack.nix b/lib/fetchPackwizModpack.nix
new file mode 100644
index 0000000..a12d098
--- /dev/null
+++ b/lib/fetchPackwizModpack.nix
@@ -0,0 +1,136 @@
+{
+ lib,
+ stdenvNoCC,
+ fetchurl,
+ packwiz-installer-bootstrap,
+ packwiz-installer,
+ jre_headless,
+ jq,
+ moreutils,
+ curl,
+ cacert,
+}: let
+ fetchPackwizModpack = {
+ pname ? "packwiz-pack",
+ version ? "",
+ url ? null,
+ hash ? "",
+ # Either 'server' or 'both' (to get client mods as well)
+ side ? "server",
+ # The derivation passes through a 'manifest' expression, that includes
+ # useful metadata (such as MC version). When providing the manifest file itself,
+ # this metadata can be used to automatically assign 'pname' and 'version'
+ #
+ # By default, if you access the 'manifest' expression, IFD will be used.
+ # If you want to use 'manifest' without IFD or a manifest file, you can
+ # also pass a manifestHash, which allows us to fetch it with
+ # builtins.fetchurl instead.
+ manifest ? null,
+ manifestHash ? null,
+ useManifest ? manifest != null,
+ ...
+ } @ args:
+ assert lib.assertMsg (url == null -> manifest != null) "a url or manifest must be provided!";
+ stdenvNoCC.mkDerivation (finalAttrs:
+ {
+ pname =
+ if useManifest
+ then finalAttrs.passthru.manifest.name
+ else pname;
+
+ version =
+ if useManifest
+ then finalAttrs.passthru.manifest.version
+ else version;
+
+ dontUnpack = true;
+
+ buildInputs = [jre_headless jq moreutils curl cacert];
+
+ buildPhase = ''
+ ${lib.optionalString (!useManifest) "curl -L \"${url}\" > pack.toml"}
+
+ java -jar ${packwiz-installer-bootstrap} \
+ --bootstrap-main-jar ${packwiz-installer} \
+ --bootstrap-no-update \
+ --no-gui \
+ --side ${side} \
+ "${
+ if useManifest
+ then manifest
+ else url
+ }"
+ '';
+
+ installPhase = ''
+ runHook preInstall
+
+ # Fix non-determinism
+ rm env-vars -r
+ jq -Sc '.' packwiz.json | sponge packwiz.json
+
+ mkdir -p $out
+ cp * -r $out/
+
+ runHook postInstall
+ '';
+
+ passthru = let
+ drv = fetchPackwizModpack args;
+ in {
+ # Pack manifest as a nix expression
+ # If manifestHash is not null or the manifest is directly provided,
+ # then we can do this without IFD.
+ # Otherwise, fallback to IFD.
+ manifest = lib.importTOML (
+ if manifestHash != null
+ then
+ builtins.fetchurl
+ {
+ inherit url;
+ sha256 = manifestHash;
+ }
+ else if useManifest
+ then manifest
+ else "${drv}/pack.toml"
+ );
+
+ # Adds an attribute set of files to the derivation.
+ # Useful to add server-specific mods not part of the pack.
+ addFiles = files:
+ stdenvNoCC.mkDerivation {
+ inherit (drv) pname version;
+ src = null;
+ dontUnpack = true;
+ dontConfig = true;
+ dontBuild = true;
+ dontFixup = true;
+
+ installPhase =
+ ''
+ cp -as "${drv}" $out
+ chmod u+w -R $out
+ ''
+ + lib.concatLines (
+ lib.mapAttrsToList
+ (name: file: ''
+ mkdir -p "$out/$(dirname "${name}")"
+ cp -as "${file}" "$out/${name}"
+ '')
+ files
+ );
+
+ passthru = {inherit (drv) manifest;};
+ meta = drv.meta or {};
+ };
+ };
+
+ dontFixup = true;
+
+ outputHashMode = "recursive";
+ outputHashAlgo = "sha256";
+ outputHash = hash;
+ }
+ // args);
+in
+ fetchPackwizModpack
diff --git a/lib/packwiz-installer-bootstrap.nix b/lib/packwiz-installer-bootstrap.nix
new file mode 100644
index 0000000..b456567
--- /dev/null
+++ b/lib/packwiz-installer-bootstrap.nix
@@ -0,0 +1,7 @@
+{fetchurl}:
+fetchurl rec {
+ pname = "packwiz-installer-bootstrap";
+ version = "0.0.3";
+ url = "https://github.com/packwiz/packwiz-installer-bootstrap/releases/download/v${version}/packwiz-installer-bootstrap.jar";
+ hash = "sha256-qPuyTcYEJ46X9GiOgtPZGjGLmO/AjV2/y8vKtkQ9EWw=";
+}
diff --git a/lib/packwiz-installer.nix b/lib/packwiz-installer.nix
new file mode 100644
index 0000000..121a48f
--- /dev/null
+++ b/lib/packwiz-installer.nix
@@ -0,0 +1,7 @@
+{fetchurl}:
+fetchurl rec {
+ pname = "packwiz-installer";
+ version = "0.5.12";
+ url = "https://github.com/packwiz/packwiz-installer/releases/download/v${version}/packwiz-installer.jar";
+ hash = "sha256-IGgdxgkGqQG5fmWT0fVHFJQEqAjKNdL2v+DgLuJqRjs=";
+}