From 1ae7384ddb3419330ab134da548dd8769b9f3d11 Mon Sep 17 00:00:00 2001 From: Matthijs Steen Date: Wed, 2 Jan 2019 01:05:51 +0100 Subject: [PATCH] openra with extra mods --- pkgs/games/openra/common.nix | 87 +++++++ pkgs/games/openra/default.nix | 129 +++++----- pkgs/games/openra/engine.nix | 60 +++++ pkgs/games/openra/engines.nix | 41 ++++ pkgs/games/openra/mkdirp.sh | 4 + pkgs/games/openra/mod-launch-game.sh | 25 ++ pkgs/games/openra/mod.nix | 104 ++++++++ pkgs/games/openra/mods.nix | 339 +++++++++++++++++++++++++++ pkgs/games/openra/openra-mod.desktop | 11 + pkgs/games/openra/packages.nix | 60 +++++ pkgs/top-level/all-packages.nix | 4 +- 11 files changed, 795 insertions(+), 69 deletions(-) create mode 100644 pkgs/games/openra/common.nix create mode 100644 pkgs/games/openra/engine.nix create mode 100644 pkgs/games/openra/engines.nix create mode 100644 pkgs/games/openra/mkdirp.sh create mode 100644 pkgs/games/openra/mod-launch-game.sh create mode 100644 pkgs/games/openra/mod.nix create mode 100644 pkgs/games/openra/mods.nix create mode 100644 pkgs/games/openra/openra-mod.desktop create mode 100644 pkgs/games/openra/packages.nix diff --git a/pkgs/games/openra/common.nix b/pkgs/games/openra/common.nix new file mode 100644 index 000000000000..e90f8170e18e --- /dev/null +++ b/pkgs/games/openra/common.nix @@ -0,0 +1,87 @@ +/* The reusable code, and package attributes, between OpenRA engine packages (engine.nix) + and out-of-tree mod packages (mod.nix). +*/ +{ stdenv, makeSetupHook, curl, unzip, dos2unix, pkgconfig, makeWrapper +, lua, mono, dotnetPackages, python +, libGL, openal, SDL2 +, zenity +}: + +with stdenv.lib; + +let + path = makeBinPath ([ mono python ] ++ optional (zenity != null) zenity); + rpath = makeLibraryPath [ lua openal SDL2 ]; + mkdirp = makeSetupHook { } ./mkdirp.sh; + +in { + patchEngine = dir: version: '' + sed -i \ + -e 's/^VERSION.*/VERSION = ${version}/g' \ + -e '/fetch-geoip-db/d' \ + -e '/GeoLite2-Country.mmdb.gz/d' \ + ${dir}/Makefile + + sed -i 's|locations=.*|locations=${lua}/lib|' ${dir}/thirdparty/configure-native-deps.sh + ''; + + wrapLaunchGame = openraSuffix: '' + # Setting TERM=xterm fixes an issue with terminfo in mono: System.Exception: Magic number is wrong: 542 + # https://github.com/mono/mono/issues/6752#issuecomment-365212655 + wrapProgram $out/lib/openra${openraSuffix}/launch-game.sh \ + --prefix PATH : "${path}" \ + --prefix LD_LIBRARY_PATH : "${rpath}" \ + --set TERM xterm + + makeWrapper $out/lib/openra${openraSuffix}/launch-game.sh $(mkdirp $out/bin)/openra${openraSuffix} \ + --run "cd $out/lib/openra${openraSuffix}" + ''; + + packageAttrs = { + buildInputs = with dotnetPackages; [ + FuzzyLogicLibrary + MaxMindDb + MaxMindGeoIP2 + MonoNat + NewtonsoftJson + NUnit3 + NUnitConsole + OpenNAT + RestSharp + SharpFont + SharpZipLib + SmartIrc4net + StyleCopMSBuild + StyleCopPlusMSBuild + ] ++ [ + lua + libGL + openal + SDL2 + ]; + + # TODO: Test if this is correct. + nativeBuildInputs = [ + curl + unzip + dos2unix + pkgconfig + makeWrapper + mkdirp + mono + python + ]; + + makeFlags = "prefix=$(out)"; + + doCheck = true; + + dontStrip = true; + + meta = { + maintainers = with maintainers; [ msteen rardiol ]; + license = licenses.gpl3; + platforms = platforms.linux; + }; + }; +} diff --git a/pkgs/games/openra/default.nix b/pkgs/games/openra/default.nix index 922d4f4762c8..bf243e610bde 100644 --- a/pkgs/games/openra/default.nix +++ b/pkgs/games/openra/default.nix @@ -1,79 +1,72 @@ -{ stdenv, fetchFromGitHub, mono, makeWrapper, lua -, SDL2, freetype, openal, systemd, pkgconfig, - dotnetPackages, gnome3, curl, unzip, which, python -}: +/* This file defines all OpenRA packages under `openraPackages`, + e.g. the OpenRA release engine can be found at `openraPackages.engines.release` (see `engines.nix`), + or the out-of-tree mod "Combined Arms" can be found at `openraPackages.mods.ca` (see `mods.nix`). + The `openra` package is just an alias to `openraPackages.engines.release`, + and just provides the mods included in the source code of the engine. + Additional engines or mods can be added with `openraPackages.buildOpenRAEngine` (function around `engine.nix`) + and `openraPackages.buildOpenRAMod` (function around `mod.nix`), respectively. +*/ +pkgs: -stdenv.mkDerivation rec { - pname = "openra"; - version = "20181215"; +with pkgs.lib; - meta = with stdenv.lib; { - description = "Real Time Strategy game engine recreating the C&C titles"; - homepage = "http://www.openra.net/"; - maintainers = [ maintainers.rardiol ]; - license = licenses.gpl3; - platforms = platforms.linux; - }; +let + /* Building an engine or out-of-tree mod is very similar, + but different enough not to be able to build them with the same package definition, + so instaed we define what is common between them in a seperate file. - src = fetchFromGitHub { - owner = "OpenRA"; - repo = "OpenRA"; - rev = "release-${version}"; - sha256 = "0p0izykjnz7pz02g2khp7msqa00jhjsrzk9y0g29dirmdv75qa4r"; + Although `callPackage` could be used, it would require undoing `makeOverridable`, + because `common.nix` does not define a package, but just an attribute set, + which is directly passed as part of the argument to the engines and mods `callPackage`, + so either the attributes added by `makeOverridable` have to be removed + or the engine and mod package definitions will need to add `...` to the argument list. + */ + common = let f = import ./common.nix; in f (builtins.intersectAttrs (functionArgs f) pkgs // { + lua = pkgs.lua5_1; + # It is not necessary to run the game, but it is nicer to be given an error dialog in the case of failure, + # rather than having to look to the logs why it is not starting. + inherit (pkgs.gnome3) zenity; + }); + /* Building a set of engines or mods requires some dependencies as well, + so the sets will actually be defined as a function instead, + requiring the dependencies and returning the actual set. + + Not all dependencies for defining a engine or mod set are shared, + so additional arguments can be passed as well. + + The builders for engines and mods allow to delay specifying the name, + by returning a function that expects a name, which we use, in this case, + to base the name on the attribute name instead, preventing the need to specify the name twice + if the attribute name and engine/mod name are equal. + */ + callWithName = name: value: if isFunction value then value name else value; + buildOpenRASet = f: args: pkgs.recurseIntoAttrs (mapAttrs callWithName (f ({ + inherit (pkgs) fetchFromGitHub; + abbrevCommit = commit: substring 0 7 commit; extraPostFetch = '' - sed -i 's,curl,curl --insecure,g' $out/thirdparty/{fetch-thirdparty-deps,noget}.sh + sed -i 's/curl/curl --insecure/g' $out/thirdparty/{fetch-thirdparty-deps,noget}.sh $out/thirdparty/fetch-thirdparty-deps.sh ''; - }; + } // args))); - dontStrip = true; +in pkgs.recurseIntoAttrs rec { + # The whole attribute set is destructered to ensure those (and only those) attributes are given + # and to provide defaults for those that are optional. + buildOpenRAEngine = { name ? null, version, description, homepage, mods, src }@engine: + # Allow specifying the name at a later point if no name has been given. + let builder = name: pkgs.callPackage ./engine.nix (common // { + engine = engine // { inherit name; }; + }); in if name == null then builder else builder name; - buildInputs = (with dotnetPackages; - [ NUnit3 NewtonsoftJson MonoNat FuzzyLogicLibrary SmartIrc4net SharpZipLib MaxMindGeoIP2 MaxMindDb SharpFont StyleCopMSBuild StyleCopPlusMSBuild RestSharp NUnitConsole OpenNAT ]) - ++ [ curl unzip lua gnome3.zenity ]; - nativeBuildInputs = [ curl unzip mono makeWrapper lua pkgconfig ]; + # See `buildOpenRAEngine`. + buildOpenRAMod = { name ? null, version, title, description, homepage, src, engine, assetsError ? "" }@mod: ({ version, mods ? [], src }@engine: + let builder = name: pkgs.callPackage ./mod.nix (common // { + mod = mod // { inherit name assetsError; }; + engine = engine // { inherit mods; }; + }); in if name == null then builder else builder name) engine; - postPatch = '' - mkdir Support - sed -i \ - -e 's/^VERSION.*/VERSION = release-${version}/g' \ - -e '/GeoLite2-Country.mmdb.gz/d' \ - -e '/fetch-geoip-db.sh/d' \ - Makefile - substituteInPlace thirdparty/configure-native-deps.sh --replace "locations=\"" "locations=\"${lua}/lib " - ''; - - preConfigure = '' - makeFlags="prefix=$out" - make version - ''; - - buildFlags = [ "DEBUG=false" "default" "man-page" ]; - - doCheck = true; - - #TODO: check - checkTarget = "nunit test"; - - installTargets = [ "install" "install-linux-icons" "install-linux-desktop" "install-linux-appdata" "install-linux-mime" "install-man-page" ]; - - postInstall = with stdenv.lib; let - runtime = makeLibraryPath [ SDL2 freetype openal systemd lua ]; - binaries= makeBinPath [ which mono gnome3.zenity python ]; - in '' - wrapProgram $out/lib/openra/launch-game.sh \ - --prefix PATH : "${binaries}" \ - --prefix LD_LIBRARY_PATH : "${runtime}" \ - --set TERM "xterm" - - mkdir -p $out/bin - makeWrapper $out/lib/openra/launch-game.sh $out/bin/openra --run "cd $out/lib/openra" - printf "#!/bin/sh\nexec $out/bin/openra Game.Mod=ra" > $out/bin/openra-ra - chmod +x $out/bin/openra-ra - printf "#!/bin/sh\nexec $out/bin/openra Game.Mod=cnc" > $out/bin/openra-cnc - chmod +x $out/bin/openra-cnc - printf "#!/bin/sh\nexec $out/bin/openra Game.Mod=d2k" > $out/bin/openra-d2k - chmod +x $out/bin/openra-d2k - ''; + # See `buildOpenRASet`. + engines = buildOpenRASet (import ./engines.nix) { inherit buildOpenRAEngine; }; + mods = buildOpenRASet (import ./mods.nix) { inherit buildOpenRAMod; }; } diff --git a/pkgs/games/openra/engine.nix b/pkgs/games/openra/engine.nix new file mode 100644 index 000000000000..7d2d007d0758 --- /dev/null +++ b/pkgs/games/openra/engine.nix @@ -0,0 +1,60 @@ +/* The package defintion for an OpenRA engine. + It shares code with `mod.nix` by what is defined in `common.nix`. + Similar to `mod.nix` it is a generic package definition, + in order to make it easy to define multiple variants of the OpenRA engine. + For each mod provided by the engine, a wrapper script is created, + matching the naming convention used by `mod.nix`. + This package could be seen as providing a set of in-tree mods, + while the `mod.nix` pacakges provide a single out-of-tree mod. +*/ +{ stdenv +, packageAttrs +, patchEngine +, wrapLaunchGame +, engine +}: + +with stdenv.lib; + +stdenv.mkDerivation (recursiveUpdate packageAttrs rec { + name = "${pname}-${version}"; + pname = "openra"; + version = "${engine.name}-${engine.version}"; + + src = engine.src; + + postPatch = patchEngine "." version; + + configurePhase = '' + runHook preConfigure + + make version VERSION=${escapeShellArg version} + + runHook postConfigure + ''; + + buildFlags = [ "DEBUG=false" "default" "man-page" ]; + + checkTarget = "nunit test"; + + installTargets = [ + "install" + "install-linux-icons" + "install-linux-desktop" + "install-linux-appdata" + "install-linux-mime" + "install-man-page" + ]; + + postInstall = '' + ${wrapLaunchGame ""} + + ${concatStrings (map (mod: '' + makeWrapper $out/bin/openra $out/bin/openra-${mod} --add-flags Game.Mod=${mod} + '') engine.mods)} + ''; + + meta = { + inherit (engine) description homepage; + }; +}) diff --git a/pkgs/games/openra/engines.nix b/pkgs/games/openra/engines.nix new file mode 100644 index 000000000000..e0d97f3c548b --- /dev/null +++ b/pkgs/games/openra/engines.nix @@ -0,0 +1,41 @@ +{ buildOpenRAEngine, fetchFromGitHub, abbrevCommit, extraPostFetch }: + +let + buildUpstreamOpenRAEngine = { version, rev, sha256 }: name: (buildOpenRAEngine { + inherit version; + description = "Open-source re-implementation of Westwood Studios' 2D Command and Conquer games"; + homepage = https://www.openra.net/; + mods = [ "cnc" "d2k" "ra" "ts" ]; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + inherit rev sha256 extraPostFetch; + }; + } name).overrideAttrs (oldAttrs: { + postInstall = '' + ${oldAttrs.postInstall} + cp -r mods/ts $out/lib/openra/mods/ + cp mods/ts/icon.png $(mkdirp $out/share/pixmaps)/openra-ts.png + ( cd $out/share/applications; sed -e 's/Dawn/Sun/g' -e 's/cnc/ts/g' openra-cnc.desktop > openra-ts.desktop ) + ''; + }); + +in { + release = buildUpstreamOpenRAEngine rec { + version = "20181215"; + rev = "release-${version}"; + sha256 = "0p0izykjnz7pz02g2khp7msqa00jhjsrzk9y0g29dirmdv75qa4r"; + }; + + playtest = buildUpstreamOpenRAEngine rec { + version = "20190106"; + rev = "playtest-${version}"; + sha256 = "0ps9x379plrrj1hnj4fpr26lc46mzgxknv5imxi0bmrh5y4781ql"; + }; + + bleed = let commit = "6de92de8d982094a766eab97a92225c240d85493"; in buildUpstreamOpenRAEngine { + version = abbrevCommit commit; + rev = commit; + sha256 = "0p0izykjnz7pz02g2khp7msqa00jhjsrzk9y0g29dirmdv75qa4r"; + }; +} diff --git a/pkgs/games/openra/mkdirp.sh b/pkgs/games/openra/mkdirp.sh new file mode 100644 index 000000000000..7b2cf0b89c0e --- /dev/null +++ b/pkgs/games/openra/mkdirp.sh @@ -0,0 +1,4 @@ +mkdirp() { + mkdir -p "$@" + echo "$@" +} diff --git a/pkgs/games/openra/mod-launch-game.sh b/pkgs/games/openra/mod-launch-game.sh new file mode 100644 index 000000000000..ec03353bee54 --- /dev/null +++ b/pkgs/games/openra/mod-launch-game.sh @@ -0,0 +1,25 @@ +#!/bin/sh +show_error() { + if command -v zenity > /dev/null; then + zenity --no-wrap --no-markup --error --title "OpenRA - @title@" --text "$1" 2>/dev/null + else + printf "$1\n" >&2 + fi + exit 1 +} + +cd "@out@/lib/openra-@name@" + +# Check for missing assets +assetsError='@assetsError@' +if [ -n "$assetsError" -a ! -d "$HOME/.openra/Content/@name@" ]; then + show_error "$assetsError" +fi + +# Run the game +mono --debug OpenRA.Game.exe Game.Mod=@name@ Engine.LaunchPath="@out@/bin/openra-@name@" Engine.ModSearchPaths="@out@/lib/openra-@name@/mods" "$@" + +# Show a crash dialog if something went wrong +if [ $? -ne 0 -a $? -ne 1 ]; then + show_error "OpenRA - @title@ has encountered a fatal error.\nPlease refer to the crash logs for more information.\n\nLog files are located in ~/.openra/Logs" +fi diff --git a/pkgs/games/openra/mod.nix b/pkgs/games/openra/mod.nix new file mode 100644 index 000000000000..ebc65b2f5c4e --- /dev/null +++ b/pkgs/games/openra/mod.nix @@ -0,0 +1,104 @@ +/* The package defintion for an OpenRA out-of-tree mod. + It shares code with `engine.nix` by what is defined in `common.nix`. + To build an out-of-tree mod it needs the source code of the engine available, + and they each need to be build with a specific version or fork of the engine, + so the engine needs to be supplied as an argument as well. + The engine is relatively small and quick to build, so this is not much of a problem. + Building a mod will result in a wrapper script that starts the mod inside the specified engine. +*/ +{ stdenv +, packageAttrs +, patchEngine +, wrapLaunchGame +, mod +, engine +}: + +with stdenv.lib; + +let + engineSourceName = engine.src.name or "engine"; + modSourceName = mod.src.name or "mod"; + +# Based on: https://build.opensuse.org/package/show/home:fusion809/openra-ura +in stdenv.mkDerivation (recursiveUpdate packageAttrs rec { + name = "${pname}-${version}"; + pname = "openra-${mod.name}"; + inherit (mod) version; + + srcs = [ + mod.src + engine.src + ]; + + sourceRoot = "."; + + postUnpack = '' + mv ${engineSourceName} ${modSourceName} + cd ${modSourceName} + ''; + + postPatch = '' + cat <<'EOF' > fetch-engine.sh + #!/bin/sh + exit 0 + EOF + + sed -i 's/^VERSION.*/VERSION = ${version}/g' Makefile + + dos2unix *.md + + ${patchEngine engineSourceName engine.version} + ''; + + configurePhase = '' + runHook preConfigure + + make version VERSION=${escapeShellArg version} + make -C ${engineSourceName} version VERSION=${escapeShellArg engine.version} + + runHook postConfigure + ''; + + checkTarget = "test"; + + installPhase = '' + runHook preInstall + + make -C ${engineSourceName} install-engine install-common-mod-files DATA_INSTALL_DIR=$out/lib/${pname} + + cp -r ${engineSourceName}/mods/{${concatStringsSep "," ([ "common" "modcontent" ] ++ engine.mods)}} mods/${mod.name} \ + $out/lib/${pname}/mods/ + + substitute ${./mod-launch-game.sh} $out/lib/${pname}/launch-game.sh \ + --subst-var out \ + --subst-var-by name ${escapeShellArg mod.name} \ + --subst-var-by title ${escapeShellArg mod.title} \ + --subst-var-by assetsError ${escapeShellArg mod.assetsError} + chmod +x $out/lib/${pname}/launch-game.sh + + ${wrapLaunchGame "-${mod.name}"} + + substitute ${./openra-mod.desktop} $(mkdirp $out/share/applications)/${pname}.desktop \ + --subst-var-by name ${escapeShellArg mod.name} \ + --subst-var-by title ${escapeShellArg mod.title} + + cp README.md $(mkdirp $out/share/doc/packages/${pname})/README.md + + [[ -e mods/${mod.name}/icon.png ]] && mod_icon=mods/${mod.name}/icon.png || { + [[ -e mods/${mod.name}/logo.png ]] && mod_icon=mods/${mod.name}/logo.png || mod_icon=packaging/linux/mod_256x256.png + } + cp "$mod_icon" $(mkdirp $out/share/pixmaps)/${pname}.png + + for size in 16 32 48 64 128 256; do + size=''${size}x''${size} + cp packaging/linux/mod_''${size}.png $(mkdirp $out/share/icons/hicolor/''${size}/apps)/${pname}.png + done + + runHook postInstall + ''; + + meta = { + inherit (mod) description homepage; + }; +}) diff --git a/pkgs/games/openra/mods.nix b/pkgs/games/openra/mods.nix new file mode 100644 index 000000000000..5bfc5a224a5c --- /dev/null +++ b/pkgs/games/openra/mods.nix @@ -0,0 +1,339 @@ +{ buildOpenRAMod, fetchFromGitHub, abbrevCommit, extraPostFetch }: + +let + unsafeBuildOpenRAMod = attrs: name: (buildOpenRAMod attrs name).overrideAttrs (_: { + doCheck = false; + }); + +in { + ca = buildOpenRAMod { + version = "93"; + title = "Combined Arms"; + description = "A game that combines units from the official OpenRA Red Alert and Tiberian Dawn mods"; + homepage = https://github.com/Inq8/CAmod; + src = fetchFromGitHub { + owner = "Inq8"; + repo = "CAmod"; + rev = "16fb77d037be7005c3805382712c33cec1a2788c"; + sha256 = "11fjyr3692cy2a09bqzk5ya1hf6plh8hmdrgzds581r9xbj0q4pr"; + }; + engine = let commit = "b8a7dd52ff893ed8225726d4ed4e14ecad748404"; in { + version = abbrevCommit commit; + src = fetchFromGitHub { + owner = "Inq8"; + repo = "CAengine" ; + rev = commit; + sha256 = "0dyk861qagibx8ldshz7d2nrki9q550f6f0wy8pvayvf1gv1dbxj"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + d2 = unsafeBuildOpenRAMod rec { + version = "128"; + title = "Dune II"; + description = "A modernization of the original ${title} game"; + homepage = https://github.com/OpenRA/d2; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "d2"; + rev = "bc969207b532a2def69e0d6ac09a4e8fb5d4e946"; + sha256 = "18v154kf1fmfk2gnymb3ggsfy73ql8rr7jvbhiw60yhzwx89cdk8"; + }; + engine = rec { + version = "20181215"; + mods = [ "cnc" "d2k" "ra" ]; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + rev = "release-${version}"; + sha256 = "0p0izykjnz7pz02g2khp7msqa00jhjsrzk9y0g29dirmdv75qa4r"; + name = "engine"; + inherit extraPostFetch; + }; + }; + assetsError = '' + The mod expects the original ${title} game assets in place: + https://github.com/OpenRA/d2/wiki + ''; + }; + + dr = buildOpenRAMod rec { + version = "244"; + title = "Dark Reign"; + description = "A re-imagination of the original Command & Conquer: ${title} game"; + homepage = https://github.com/drogoganor/DarkReign; + src = fetchFromGitHub { + owner = "drogoganor"; + repo = "DarkReign"; + rev = "e21db398f4d995c91b9e1a0f31ffaa7d54f43742"; + sha256 = "1gzvdf6idmx0rr8afaxd9dsbnxljif2kic6znkd9vcrwnqmp1fjr"; + }; + engine = let commit = "7fcfb1dcb2bd472fa6680ffa37bd3bbedb2c44c5"; in { + version = abbrevCommit commit; + src = fetchFromGitHub { + owner = "drogoganor"; + repo = "OpenRA" ; + rev = commit; + sha256 = "0x7k96j3q16dgay4jjlyv9kcgn4sc4v9ksw6ijnjws7q1r2rjs0m"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + gen = buildOpenRAMod { + version = "1133"; + title = "Generals Alpha"; + description = "Re-imagination of the original Command & Conquer: Generals game"; + homepage = https://github.com/MustaphaTR/Generals-Alpha; + src = fetchFromGitHub { + owner = "MustaphaTR"; + repo = "Generals-Alpha"; + rev = "277d20d5a8b5e11eac9443031af133dc110c653f"; + sha256 = "1k37545l99q7zphnh1ykvimsyp5daykannps07d4dgr2w9l7bmhg"; + }; + engine = rec { + version = "gen-20180905"; + src = fetchFromGitHub { + owner = "MustaphaTR"; + repo = "OpenRA" ; + rev = version; + sha256 = "0wy1h7fg0n8dpy6y91md7x0qnr9rk4xf6155jali4bi8gghw2g5v"; + name = "generals-alpha-engine"; + inherit extraPostFetch; + }; + }; + }; + + kknd = buildOpenRAMod rec { + version = "142"; + title = "Krush, Kill 'n' Destroy"; + description = "Re-imagination of the original ${title} game"; + homepage = https://kknd-game.com/; + src = fetchFromGitHub { + owner = "IceReaper"; + repo = "KKnD"; + rev = "54d34292168d5c47529688c8d5ca7693c4001ef3"; + sha256 = "1rsdig282cfr8b4iamr9ri6sshgppp8gllfyib6c2hvqqr301720"; + }; + engine = let commit = "4e8eab4ca00d1910203c8a103dfd2c002714daa8"; in { + version = abbrevCommit commit; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + rev = commit; + sha256 = "1yyqparf93x8yzy1f46gsymgkj5jls25v2yc7ighr3f7mi3igdvq"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + mw = buildOpenRAMod rec { + version = "235"; + title = "Medieval Warfare"; + description = "A re-imagination of the original Command & Conquer: ${title} game"; + homepage = https://github.com/CombinE88/Medieval-Warfare; + src = fetchFromGitHub { + owner = "CombinE88"; + repo = "Medieval-Warfare"; + rev = "1e4fc7ea24d0806c5a7cd753490e967d804a3567"; + sha256 = "0swa66mzb6wr8vf1yivrss54dl98jzzwh9b8qrjfwmfrq2i356iq"; + }; + engine = let commit = "9f9617aa359ebc1923252b7a4a79def73ecfa8a2"; in { + version = abbrevCommit commit; + src = fetchFromGitHub { + owner = "CombinE88"; + repo = "OpenRA" ; + rev = commit; + sha256 = "02h29xnc1cb5zr001cnmaww5qnfnfaza4v28251jgzkby593r32q"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + ra2 = buildOpenRAMod rec { + version = "876"; + title = "Red Alert 2"; + description = "Re-imagination of the original Command & Conquer: ${title} game"; + homepage = https://github.com/OpenRA/ra2; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "ra2"; + rev = "6a864b2a5887ae42291768fb3dec73082fee44ee"; + sha256 = "19m4z9r00dj67746ps2f9a8i1icq8nm0iiww6dl975yl6gaxp5qy"; + }; + engine = rec { + version = "20180923"; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + rev = "release-${version}"; + sha256 = "1pgi3zaq9fwwdq6yh19bwxscslqgabjxkvl9bcn1a5agy4bfbqk5"; + name = "engine"; + inherit extraPostFetch; + }; + }; + assetsError = '' + The mod expects the original ${title} game assets in place: + https://github.com/OpenRA/ra2/wiki + ''; + }; + + raclassic = buildOpenRAMod { + version = "171"; + title = "Red Alert Classic"; + description = "A modernization of the original Command & Conquer: Red Alert game"; + homepage = https://github.com/OpenRA/raclassic; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "raclassic"; + rev = "a2319b3dfb367a8d4278bf7baf55a10abf615fbc"; + sha256 = "1k67fx4d9hg8mckzp7pp8lxa6ngqxnnrnbqyfls99dqc4df1iw0a"; + }; + engine = rec { + version = "20181215"; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + rev = "release-${version}"; + sha256 = "0p0izykjnz7pz02g2khp7msqa00jhjsrzk9y0g29dirmdv75qa4r"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + rv = unsafeBuildOpenRAMod { + version = "1294"; + title = "Romanov's Vengeance"; + description = "Re-imagination of the original Command & Conquer: Red Alert 2 game"; + homepage = https://github.com/MustaphaTR/Romanovs-Vengeance; + src = fetchFromGitHub { + owner = "MustaphaTR"; + repo = "Romanovs-Vengeance"; + rev = "c21cb11579d7e12354c5ccb5c3c47e567c6b3d4f"; + sha256 = "1vmc5b9awx8q0mahwv11fzgplw9w7m8kzvnx5cl7xr1w5wk87428"; + }; + engine = let commit = "e9e99074b294c32fbe88dd8727581cb8c512c2e2"; in { + version = abbrevCommit commit; + mods = [ "as" ]; + src = fetchFromGitHub { + owner = "GraionDilach"; + repo = "OpenRA" ; + rev = commit; + sha256 = "0bibnakpmbxwglf2dka6g04xp8dzwyms1zk5kqlbm8gpdp0aqmxp"; + name = "engine"; + inherit extraPostFetch; + }; + }; + assetsError = '' + The mod expects the Command & Conquer: The Ultimate Collection assets in place: + https://github.com/OpenRA/ra2/wiki + ''; + }; + + sp = unsafeBuildOpenRAMod { + version = "153"; + title = "Shattered Paradise"; + description = "Re-imagination of the original Command & Conquer: Tiberian Sun game"; + homepage = https://github.com/ABrandau/OpenRAModSDK; + src = fetchFromGitHub { + owner = "ABrandau"; + repo = "OpenRAModSDK"; + rev = "89148b8cf89bf13911fafb74a1aa2b4cacf027e0"; + sha256 = "1bb8hzd3mhnn76iqiah1161qz98f0yvyryhmrghq03xlbin3mhbi"; + }; + engine = let commit = "82a2f234bdf3b768cea06408e3de30f9fbbe9412"; in { + version = abbrevCommit commit; + mods = [ "as" "ts" ]; + src = fetchFromGitHub { + owner = "ABrandau"; + repo = "OpenRA" ; + rev = commit; + sha256 = "1nl3brvx1bikxm5rmpc7xmd32n722jiyjh86pnar6b6idr1zj2ws"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + ss = buildOpenRAMod rec { + version = "72"; + title = "Sole Survivor"; + description = "A re-imagination of the original Command & Conquer: ${title} game"; + homepage = https://github.com/MustaphaTR/sole-survivor; + src = fetchFromGitHub { + owner = "MustaphaTR"; + repo = "sole-survivor"; + rev = "fad65579c8b487cef9a8145e872390ed77c16c69"; + sha256 = "0h7is7x2qyvq7vqp0jgw5zrdkw8g7ndd82d843ldhnb0a3vyrk34"; + }; + engine = let commit = "becfc154c5cd3891d695339ff86883db8b5790a5"; in { + version = abbrevCommit commit; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + rev = commit; + sha256 = "0id8vf3cjr7h5pz4sw8pdaz3sc45lxr21k1fk4309kixsrpa7i0y"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + ura = buildOpenRAMod { + version = "431"; + title = "Red Alert Unplugged"; + description = "Re-imagination of the original Command & Conquer: Red Alert game"; + homepage = http://redalertunplugged.com/; + src = fetchFromGitHub { + owner = "RAunplugged"; + repo = "uRA"; + rev = "128dc53741fae923f4af556f2293ceaa0cf571f0"; + sha256 = "1mhr8kyh313z52gdrqv31d6z7jvdldiajalca5mcr8gzg6mph66p"; + }; + engine = rec { + version = "unplugged-cd82382"; + src = fetchFromGitHub { + owner = "RAunplugged"; + repo = "OpenRA" ; + rev = version; + sha256 = "1p5hgxxvxlz8480vj0qkmnxjh7zj3hahk312m0zljxfdb40652w1"; + name = "engine"; + inherit extraPostFetch; + }; + }; + }; + + yr = unsafeBuildOpenRAMod rec { + version = "117"; + homepage = https://github.com/cookgreen/yr; + title = "Yuri's Revenge"; + description = "Re-imagination of the original Command & Conquer: ${title} game"; + src = fetchFromGitHub { + owner = "cookgreen"; + repo = "yr"; + rev = "1d4beeb0687fe4b39b01ec31f3702cfb90a7f4f7"; + sha256 = "1rd962ja1x72rz68kbmp19yiip3iif50hzlj3v8k1f5l94r2x2pn"; + }; + engine = rec { + version = "20180923"; + src = fetchFromGitHub { + owner = "OpenRA"; + repo = "OpenRA" ; + rev = "release-${version}"; + sha256 = "1pgi3zaq9fwwdq6yh19bwxscslqgabjxkvl9bcn1a5agy4bfbqk5"; + name = "engine"; + inherit extraPostFetch; + }; + }; + assetsError = '' + The mod expects the Command & Conquer: The Ultimate Collection assets in place: + https://github.com/OpenRA/ra2/wiki + ''; + }; +} diff --git a/pkgs/games/openra/openra-mod.desktop b/pkgs/games/openra/openra-mod.desktop new file mode 100644 index 000000000000..090b6c1325d1 --- /dev/null +++ b/pkgs/games/openra/openra-mod.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=OpenRA - @title@ +GenericName=Real Time Strategy Game +GenericName[de]=Echtzeit-Strategiespiel +Comment=@description@ +Icon=openra-@name@ +Exec=openra-@name@ +Terminal=false +Categories=Game;StrategyGame;X-RTS;X-RealTimeStrategy;X-RealTimeStrategyGame; diff --git a/pkgs/games/openra/packages.nix b/pkgs/games/openra/packages.nix new file mode 100644 index 000000000000..c09b697771a3 --- /dev/null +++ b/pkgs/games/openra/packages.nix @@ -0,0 +1,60 @@ +pkgs: + +let + /* Building an engine or out-of-tree mod is very similar, + but different enough not to be able to build them with the same package definition, + so instaed we define what is common between them in a seperate file. + + Although `callPackage` could be used, it would require undoing `makeOverridable`, + because `common.nix` does not define a package, but just an attribute set, + which is directly passed as part of the argument to the engines and mods `callPackage`, + so either the attributes added by `makeOverridable` have to be removed + or the engine and mod package definitions will need to add `...` to the argument list. + */ + common = let f = import ./common.nix; in f (builtins.intersectAttrs (builtins.functionArgs f) pkgs // { + lua = pkgs.lua5_1; + # It is not necessary to run the game, but it is nicer to be given an error dialog in the case of failure, + # rather than having to look to the logs why it is not starting. + inherit (pkgs.gnome3) zenity; + }); + + /* Building a set of engines or mods requires some dependencies as well, + so the sets will actually be defined as a function instead, + requiring the dependencies and returning the actual set. + + Not all dependencies for defining a engine or mod set are shared, + so additional arguments can be passed as well. + + The builders for engines and mods allow to delay specifying the name, + by returning a function that expects a name, which we use, in this case, + to base the name on the attribute name instead, preventing the need to specify the name twice + if the attribute name and engine/mod name are equal. + */ + buildOpenRASet = f: args: builtins.mapAttrs (name: value: if builtins.isFunction value then value name else value) (f ({ + inherit (pkgs) fetchFromGitHub; + extraPostFetch = '' + sed -i 's/curl/curl --insecure/g' $out/thirdparty/{fetch-thirdparty-deps,noget}.sh + $out/thirdparty/fetch-thirdparty-deps.sh + ''; + } // args)); + +in rec { + # The whole attribute set is destructered to ensure those (and only those) attributes are given + # and to provide defaults for those that are optional. + buildOpenRAEngine = { name ? null, version, description, homepage, mods, src, installExperimental ? "" }@engine: + # Allow specifying the name at a later point if no name has been given. + let builder = name: pkgs.callPackage ./engine.nix (common // { + engine = engine // { inherit name installExperimental; }; + }); in if name == null then builder else builder name; + + # See `buildOpenRAEngine`. + buildOpenRAMod = { name ? null, version, title, description, homepage, src, engine }@mod: ({ version, mods ? [], src }@engine: + let builder = name: pkgs.callPackage ./mod.nix (common // { + mod = mod // { inherit name; }; + engine = engine // { inherit mods; }; + }); in if name == null then builder else builder name) engine; + + # See `buildOpenRASet`. + engines = buildOpenRASet (import ./engines.nix) { inherit buildOpenRAEngine; }; + mods = buildOpenRASet (import ./mods.nix) { inherit buildOpenRAMod; }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 992f578c211c..d6be20537282 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -20805,7 +20805,9 @@ in openmw-tes3mp = libsForQt5.callPackage ../games/openmw/tes3mp.nix { }; - openra = callPackage ../games/openra { lua = lua5_1; }; + openraPackages = import ../games/openra pkgs; + + openra = openraPackages.engines.release; openrw = callPackage ../games/openrw { };