From a9e36107445f7675014be620c2763b238ef719df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Sun, 25 Apr 2021 04:50:30 +0100 Subject: [PATCH] Add support for building minecraft modpacks --- flake.nix | 27 +++++++++++++----- lib/default.nix | 8 ++++++ lib/minecraft.nix | 30 ++++++++++++++++++++ pkgs/build-support/fetchFromCurseForge.nix | 23 ++++++++++++++++ pkgs/default.nix | 12 ++++++-- pkgs/minecraft/forge-server.nix | 32 +++++++++++++++++++++- 6 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 lib/default.nix create mode 100644 lib/minecraft.nix create mode 100644 pkgs/build-support/fetchFromCurseForge.nix diff --git a/flake.nix b/flake.nix index 17cf407..e0c42c7 100644 --- a/flake.nix +++ b/flake.nix @@ -21,7 +21,7 @@ }; }; - outputs = { nixpkgs, nixos-hardware, flake-utils, tlaternet-webserver + outputs = { self, nixpkgs, nixos-hardware, flake-utils, tlaternet-webserver , tlaternet-templates, ... }@inputs: let overlays = [ @@ -30,14 +30,18 @@ tlaternet-webserver.legacyPackages.${prev.system}.packages; tlaternet-templates = tlaternet-templates.legacyPackages.${prev.system}.packages; - local = import ./pkgs { pkgs = prev; }; + local = import ./pkgs { + pkgs = prev; + local-lib = self.lib.${prev.system}; + }; }) ]; in { nixosConfigurations = { - tlaternet = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; + tlaternet = let system = "x86_64-linux"; + in nixpkgs.lib.nixosSystem { + inherit system; modules = [ ({ modulesPath, ... }: { @@ -52,8 +56,9 @@ ]; }; - vm = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; + vm = let system = "x86_64-linux"; + in nixpkgs.lib.nixosSystem { + inherit system; modules = [ ({ modulesPath, ... }: { @@ -88,6 +93,14 @@ ''; }; - packages = import ./pkgs { inherit pkgs; }; + packages = import ./pkgs { + inherit pkgs; + local-lib = self.lib.${system}; + }; + + lib = import ./lib { + inherit pkgs inputs; + lib = nixpkgs.lib; + }; }); } diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..3d657e4 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,8 @@ +{ inputs, lib, pkgs, ... }: + +let + inherit (lib) makeExtensible foldr attrValues; + tlater-lib = makeExtensible (self: + let callLibs = file: import file { inherit self lib pkgs inputs; }; + in { minecraft = callLibs ./minecraft.nix; }); +in tlater-lib.extend (self: super: foldr (a: b: a // b) { } (attrValues super)) diff --git a/lib/minecraft.nix b/lib/minecraft.nix new file mode 100644 index 0000000..87d5402 --- /dev/null +++ b/lib/minecraft.nix @@ -0,0 +1,30 @@ +{ lib, pkgs, ... }: + +{ + # Make a modpack given its mod inputs. + # + # Mods should be attrsets in this format: + # { + # project = ""; + # id = ""; + # filename = ""; + # sha256 = ""; + # } + # + # This may be nice to read from a json ;) + # + mkModpack = { name, version, mods }: + pkgs.stdenv.mkDerivation { + inherit name version; + srcs = map pkgs.local.fetchFromCurseForge mods; + + sourceRoot = "src/"; + preUnpack = "mkdir -p src/"; + unpackCmd = "cp $curSrc src/"; + + installPhase = '' + mkdir -p $out/mods/ + cp * $out/mods + ''; + }; +} diff --git a/pkgs/build-support/fetchFromCurseForge.nix b/pkgs/build-support/fetchFromCurseForge.nix new file mode 100644 index 0000000..4fde62e --- /dev/null +++ b/pkgs/build-support/fetchFromCurseForge.nix @@ -0,0 +1,23 @@ +{ lib, fetchurl }: + +with builtins; + +{ project, id, filename, ... }@args: + +let + # I think this is supposed to be some weak automation + # protection. This split "id" is simply part of the download URL. + # + # Note that if it's zero-prefixed we need to remove the zeroes. It's + # really an odd one... + a = head (match "0*([[:digit:]]+)" (substring 0 4 id)); + b = head (match "0*([[:digit:]]+)" (substring 4 7 id)); + + url = "https://media.forgecdn.net/files/${a}/${b}/${filename}"; + otherArgs = removeAttrs args [ "project" "id" "filename" ]; + +in fetchurl (otherArgs // { + inherit url; + # Rename files to avoid names incompatible with the nix store + name = "${project}.jar"; +}) diff --git a/pkgs/default.nix b/pkgs/default.nix index 1089cbd..309095e 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,6 +1,12 @@ -{ pkgs, ... }: +{ pkgs, local-lib, ... }: -{ +let + inherit (pkgs.lib) callPackageWith; + callPackage = callPackageWith (pkgs // { inherit local-lib; }); +in { # Forge - forge-server = pkgs.callPackage ./minecraft/forge-server.nix { }; + forge-server = callPackage ./minecraft/forge-server.nix { }; + + # Build support + fetchFromCurseForge = callPackage ./build-support/fetchFromCurseForge.nix { }; } diff --git a/pkgs/minecraft/forge-server.nix b/pkgs/minecraft/forge-server.nix index 047a04a..a01367e 100644 --- a/pkgs/minecraft/forge-server.nix +++ b/pkgs/minecraft/forge-server.nix @@ -1,4 +1,5 @@ -{ lib, stdenv, fetchurl, jre_headless, runtimeShell }: +{ lib, stdenv, fetchurl, busybox, coreutils, jre_headless, runtimeShell +, mods ? null, config ? null, defaultconfigs ? null }: let name = "forge-server"; @@ -45,6 +46,35 @@ in stdenv.mkDerivation rec { #!${runtimeShell} set -eu + # Delete any previous mods directory so that it can be updated + ${busybox}/bin/rm -fr mods + + ${lib.optionalString (mods != null) '' + # Copy the specified mods into the directory. Note that, sadly, + # forge doesn't support symlinks here. + ${busybox}/bin/mkdir -p mods + ${busybox}/bin/cp -r '${mods}/mods/'*.jar mods + ''} + + # Delete any previous config directories so that they can be updated + ${busybox}/bin/rm -fr config defaultconfigs + + ${lib.optionalString (config != null) '' + # Copy the specified configs into the directory. Forge (and + # mods) will try to write here, so we cannot symlink. + ${busybox}/bin/mkdir -p config + ${busybox}/bin/cp -r '${config}'/* config + ${busybox}/bin/chmod -R u+w config + ''} + + ${lib.optionalString (defaultconfigs != null) '' + # Copy the specified configs into the directory. Forge (and + # mods) will try to write here, so we cannot symlink. + ${busybox}/bin/mkdir -p defaultconfigs + ${busybox}/bin/cp -r '${defaultconfigs}'/* defaultconfigs + ${busybox}/bin/chmod -R u+w defaultconfigs + ''} + exec ${jre_headless}/bin/java \$@ -jar $out'/lib/forge/forge-${version}.jar' nogui EOF