diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/default.nix | 180 | ||||
| -rw-r--r-- | lib/fetchPackwizModpack.nix | 136 | ||||
| -rw-r--r-- | lib/packwiz-installer-bootstrap.nix | 7 | ||||
| -rw-r--r-- | lib/packwiz-installer.nix | 7 |
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="; +} |
