about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--pkgs/games/COPYING20
-rw-r--r--pkgs/games/LICENSE.APACHE202
-rw-r--r--pkgs/games/base-module.nix15
-rw-r--r--pkgs/games/default.nix25
-rw-r--r--pkgs/games/humblebundle/bastion.nix62
-rw-r--r--pkgs/games/humblebundle/cavestoryplus.nix39
-rw-r--r--pkgs/games/humblebundle/default.nix50
-rw-r--r--pkgs/games/humblebundle/fetch-humble-bundle/default.nix87
-rw-r--r--pkgs/games/humblebundle/fez.nix35
-rw-r--r--pkgs/games/humblebundle/ftl.nix38
-rw-r--r--pkgs/games/humblebundle/guacamelee.nix61
-rw-r--r--pkgs/games/humblebundle/hammerwatch.nix40
-rw-r--r--pkgs/games/humblebundle/jamestown.nix55
-rw-r--r--pkgs/games/humblebundle/liads.nix43
-rw-r--r--pkgs/games/humblebundle/megabytepunch.nix18
-rw-r--r--pkgs/games/humblebundle/rocketbirds.nix11
-rw-r--r--pkgs/games/humblebundle/spaz.nix39
-rw-r--r--pkgs/games/humblebundle/swordsandsoldiers.nix43
-rw-r--r--pkgs/games/humblebundle/unepic.nix44
-rw-r--r--pkgs/games/steam/default.nix38
-rw-r--r--pkgs/games/steam/fetchsteam/default.nix91
-rw-r--r--pkgs/games/steam/fetchsteam/downloader.patch34
-rw-r--r--pkgs/games/steam/starbound.nix132
23 files changed, 1222 insertions, 0 deletions
diff --git a/pkgs/games/COPYING b/pkgs/games/COPYING
new file mode 100644
index 00000000..581a4b68
--- /dev/null
+++ b/pkgs/games/COPYING
@@ -0,0 +1,20 @@
+Everything except files that end with ".patch" are copyright (C) 2014
+aszlig and licensed under the Apache License, Version 2.0 (the
+"License"); you may not use these files except in compliance with the
+License. You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+If the URL to the license is unavailable, please see LICENSE.APACHE in
+this directory.
+
+All of the .patch files are copyright (C) 2014 aszlig as well, but are
+licensed under the licenses of the corresponding projects. Please look
+at accompanying Nix expressions for more information about the
+licenses of the respective projects and thus my patches.
diff --git a/pkgs/games/LICENSE.APACHE b/pkgs/games/LICENSE.APACHE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/pkgs/games/LICENSE.APACHE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/pkgs/games/base-module.nix b/pkgs/games/base-module.nix
new file mode 100644
index 00000000..08855379
--- /dev/null
+++ b/pkgs/games/base-module.nix
@@ -0,0 +1,15 @@
+{ lib, ... }:
+
+with lib;
+
+{
+  options = {
+    packages = mkOption {
+      type = types.attrsOf types.unspecified;
+      default = {};
+      description = "Available NixGames packages.";
+    };
+  };
+
+  config._module.args.pkgs = import <nixpkgs> {};
+}
diff --git a/pkgs/games/default.nix b/pkgs/games/default.nix
new file mode 100644
index 00000000..d85bd191
--- /dev/null
+++ b/pkgs/games/default.nix
@@ -0,0 +1,25 @@
+{ configuration ? null }:
+
+let
+  configFilePath = let
+    xdgConfig = builtins.getEnv "XDG_CONFIG_HOME";
+    fallback = "${builtins.getEnv "HOME"}/.config";
+    basedir = if xdgConfig == "" then fallback else xdgConfig;
+  in "${basedir}/nixgames.nix";
+
+  configFile = if !builtins.pathExists configFilePath then throw ''
+    The config file "${configFilePath}" doesn't exist! Be sure to create it and
+    put your HumbleBundle email address and password in it, like this:
+
+    {
+      humblebundle.email = "fancyuser@example.com";
+      humblebundle.password = "my_super_secret_password";
+    }
+  '' else configFilePath;
+
+in ((import <nixpkgs/lib>).evalModules {
+  modules = [
+    (if configuration == null then configFilePath else configuration)
+    ./base-module.nix ./humblebundle ./steam
+  ];
+}).config.packages
diff --git a/pkgs/games/humblebundle/bastion.nix b/pkgs/games/humblebundle/bastion.nix
new file mode 100644
index 00000000..b4acda6b
--- /dev/null
+++ b/pkgs/games/humblebundle/bastion.nix
@@ -0,0 +1,62 @@
+{ stdenv, fetchHumbleBundle, lzma, xorg, libpulseaudio}:
+
+let
+  arch = {
+    "i686-linux" = "x86";
+    "x86_64-linux" = "x86_64";
+  }.${stdenv.system};
+in stdenv.mkDerivation rec {
+  name = "bastion-1.4";
+
+  src = fetchHumbleBundle {
+    name = "Bastion-HIB-2012-06-20.sh";
+    machineName = "bastion_linux";
+    downloadName = ".sh";
+    md5 = "aa6ccaead3b4b8a5fbd156f4019e8c8b";
+  };
+
+  dontStrip = true;
+  phases = ["installPhase"];
+
+  installPhase = let
+    rpath = stdenv.lib.makeLibraryPath [
+      "$dest"
+      xorg.libX11
+      xorg.libXi
+      stdenv.cc.cc
+      libpulseaudio
+    ];
+   in ''
+    dest="$out/opt/games/bastion"
+    libdir="$dest/lib" #${stdenv.lib.optionalString (arch=="x86_64") "64"}"
+
+    # Unpack binaries and data into $dest
+    mkdir -p "$dest"
+    sh "$src" --tar xf ./instarchive_all -O           | ${lzma}/bin/lzcat | tar x -C "$dest"
+    sh "$src" --tar xf ./instarchive_linux_${arch} -O | ${lzma}/bin/lzcat | tar x -C "$dest"
+
+    # Ensure that $dest is a valid library path.
+    mv $dest/lib64 $libdir || true
+
+    # Patch heavily :-)
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${rpath}" "$dest/Bastion.bin.${arch}"
+    patchelf --set-rpath "${rpath}" "$libdir/libmono-2.0.so.1"
+    patchelf --set-rpath "${rpath}" "$libdir/libfmodex.so"
+    patchelf --set-rpath "${rpath}" "$libdir/libSDL-1.2.so.0"
+
+    # Fixup permissions, just to be sure.
+    find "$dest" -type f -exec chmod 644 "{}" +
+    chmod 755 "$dest/Bastion.bin.${arch}"
+
+    # Taken from ArchLinux; might be useful to actually implement
+    #install -Dm644 "''${pkgname}".desktop "''${pkgdir}"/usr/share/applications/"''${pkgname}".desktop
+    #install -Dm755 "mesa''${pkgname}" "''${pkgdir}"/usr/bin/"''${pkgname}"mesa
+    #install -Dm644 "''${pkgdir}"/opt/games/Bastion/Bastion.png "''${pkgdir}"/usr/share/icons/"''${pkgname}".png
+
+    # XXX: Make wrapper instead of symlink ? See ArchLinux's bastionmesa above.
+    mkdir -p "$out/bin"
+    ln -s "$dest/Bastion.bin.${arch}" "$out/bin/bastion"
+  '';
+}
diff --git a/pkgs/games/humblebundle/cavestoryplus.nix b/pkgs/games/humblebundle/cavestoryplus.nix
new file mode 100644
index 00000000..d4c744d4
--- /dev/null
+++ b/pkgs/games/humblebundle/cavestoryplus.nix
@@ -0,0 +1,39 @@
+{ stdenv, fetchHumbleBundle, makeWrapper, SDL, mesa }:
+
+stdenv.mkDerivation rec {
+  name = "cave-story-plus-${version}";
+  version = "r100";
+
+  src = fetchHumbleBundle {
+    machineName = "cavestoryplus_linux";
+    downloadName = ".tar.bz2";
+    suffix = "tar.bz2";
+    md5 = "b7ecd65644b8607bc177d7ce670f2185";
+  };
+
+  buildInputs = [ makeWrapper ];
+
+  patchPhase = let
+    rpath = stdenv.lib.makeLibraryPath [
+      SDL "$out" stdenv.cc.cc mesa
+    ];
+  in ''
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${rpath}" CaveStory+_64
+  '';
+
+  installPhase = ''
+    install -vD CaveStory+_64 "$out/libexec/cave-story-plus/cave-story-plus"
+    mkdir -p "$out/bin"
+    makeWrapper \
+      "$out/libexec/cave-story-plus/cave-story-plus" \
+      "$out/bin/cave-story-plus" \
+      --run "cd '$out/share/cave-story-plus'"
+
+    mkdir -p "$out/share/cave-story-plus"
+    cp -vrt "$out/share/cave-story-plus" data
+  '';
+
+  dontStrip = true;
+}
diff --git a/pkgs/games/humblebundle/default.nix b/pkgs/games/humblebundle/default.nix
new file mode 100644
index 00000000..237a5dc6
--- /dev/null
+++ b/pkgs/games/humblebundle/default.nix
@@ -0,0 +1,50 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.humblebundle;
+
+  self = rec {
+    callPackage = pkgs.lib.callPackageWith (pkgs // self);
+    callPackage_i686 = pkgs.lib.callPackageWith (pkgs.pkgsi686Linux // self);
+
+    fetchHumbleBundle = callPackage ./fetch-humble-bundle {
+      inherit (config.humblebundle) email password;
+    };
+
+    bastion = callPackage ./bastion.nix {};
+    cavestoryplus = callPackage ./cavestoryplus.nix {};
+    fez = callPackage ./fez.nix {};
+    ftl = callPackage ./ftl.nix {};
+    guacamelee = callPackage_i686 ./guacamelee.nix {};
+    hammerwatch = callPackage ./hammerwatch.nix {};
+    jamestown = callPackage ./jamestown.nix {};
+    liads = callPackage ./liads.nix {};
+    megabytepunch = callPackage ./megabytepunch.nix {};
+    rocketbirds = callPackage ./rocketbirds.nix {};
+    spaz = callPackage ./spaz.nix {};
+    swordsandsoldiers = callPackage ./swordsandsoldiers.nix {};
+    unepic = callPackage ./unepic.nix {};
+  };
+in with lib; {
+  options.humblebundle = {
+    email = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        Email address for your HumbleBundle account.
+      '';
+    };
+
+    password = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        Password for your HumbleBundle account.
+      '';
+    };
+  };
+
+  config.packages = {
+    humblebundle = mkIf (cfg.email != null && cfg.password != null) self;
+  };
+}
diff --git a/pkgs/games/humblebundle/fetch-humble-bundle/default.nix b/pkgs/games/humblebundle/fetch-humble-bundle/default.nix
new file mode 100644
index 00000000..fbabaa8c
--- /dev/null
+++ b/pkgs/games/humblebundle/fetch-humble-bundle/default.nix
@@ -0,0 +1,87 @@
+{ stdenv, curl, cacert, writeText, fetchFromGitHub, fetchpatch
+, python, buildPythonPackage, pythonPackages
+
+, email, password
+}:
+
+{ name ? null, machineName, downloadName ? "Download", suffix ? "humblebundle", md5 }: let
+  cafile = "${cacert}/etc/ssl/certs/ca-bundle.crt";
+
+  humbleAPI = buildPythonPackage rec {
+    name = "humblebundle-${version}";
+    version = "0.1.1";
+
+    src = fetchFromGitHub {
+      owner = "saik0";
+      repo = "humblebundle-python";
+      rev = version;
+      sha256 = "1kcg42nh7sbjabim1pbqx14468pypznjy7fx2bv7dicy0sqd9b8j";
+    };
+
+    propagatedBuildInputs = with pythonPackages; [ requests2 ];
+  };
+
+  pyStr = str: "'${stdenv.lib.escape ["'" "\\"] str}'";
+
+  getDownloadURL = writeText "gethburl.py" ''
+    import sys, humblebundle
+
+    def get_products(client):
+      gamekeys = client.get_gamekeys()
+      for gamekey in gamekeys:
+        order = hb.get_order(gamekey)
+        if order.subproducts is None:
+          continue
+        for subproduct in order.subproducts:
+          prodname = subproduct.human_name.encode('ascii', 'replace')
+          downloads = [(download.machine_name, download.download_struct)
+                       for download in subproduct.downloads]
+          yield (prodname, downloads)
+
+    def find_download(downloads):
+      for machine_name, dstruct in sum(downloads.values(), []):
+        if machine_name == ${pyStr machineName}:
+          for ds in dstruct:
+            if ds.name == ${pyStr downloadName}:
+              return ds
+          print >>sys.stderr, \
+            ${pyStr "Unable to find ${downloadName} for ${machineName}!"}
+          print >>sys.stderr, 'Available download types:'
+          for ds in dstruct:
+            print >>sys.stderr, "  " + ds.name
+          raise SystemExit(1)
+
+    hb = humblebundle.HumbleApi()
+    hb.login(${pyStr email}, ${pyStr password})
+    products = dict(get_products(hb))
+    dstruct = find_download(products)
+
+    if dstruct is None:
+      print >>sys.stderr, ${pyStr "Cannot find download for ${machineName}!"}
+      print >>sys.stderr, 'Available machine names:'
+      for name, dstructs in sorted(products.items(), key=lambda x: x[0]):
+        print >>sys.stderr, "  * " + name
+        print >>sys.stderr, "    " + ', '.join(map(lambda x: x[0], dstructs))
+      raise SystemExit(1)
+    elif dstruct.md5 != ${pyStr md5}:
+      print >>sys.stderr, \
+        ${pyStr "MD5 for ${machineName} is not ${md5} but "} \
+        + dstruct.md5 + '.'
+      raise SystemExit(1)
+    else:
+      print dstruct.url.web
+  '';
+in stdenv.mkDerivation {
+  name = if name != null then name else "${machineName}.${suffix}";
+  outputHashAlgo = "md5";
+  outputHash = md5;
+
+  buildInputs = [ python humbleAPI ];
+
+  buildCommand = ''
+    url="$(python "${getDownloadURL}")"
+    header "downloading $name from $url"
+    ${curl}/bin/curl --cacert "${cafile}" --fail --output "$out" "$url"
+    stopNest
+  '';
+}
diff --git a/pkgs/games/humblebundle/fez.nix b/pkgs/games/humblebundle/fez.nix
new file mode 100644
index 00000000..5f23b97c
--- /dev/null
+++ b/pkgs/games/humblebundle/fez.nix
@@ -0,0 +1,35 @@
+{ stdenv, fetchHumbleBundle, unzip, mono, openal, SDL2 }:
+
+let
+  version = "1.0.2";
+  usVersion = stdenv.lib.replaceChars ["."] ["_"] version;
+in stdenv.mkDerivation rec {
+  name = "fez-${version}";
+  version = "09152013";
+
+  src = fetchHumbleBundle {
+    name = "${name}-bin";
+    md5 = "4ac954101835311f3528f5369e1fecb7";
+  };
+
+  unpackPhase = ''
+    ${unzip}/bin/unzip -qq "$src" 'data/*' || true
+    sourceRoot=data
+  '';
+
+  dontStrip = true;
+
+  buildPhase = ''
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${stdenv.lib.makeLibraryPath [ mono openal SDL2 ]}" \
+      FEZ.bin.x86_64
+  '';
+
+  installPhase = ''
+    ensureDir "$out/bin" "$out/libexec/fez/mono/2.0"
+    install -vD FEZ.bin.x86_64 "$out/libexec/fez/fez"
+    install -vt "$out/libexec/fez/mono/2.0" *.dll
+    ln -s "$out/libexec/fez/fez" "$out/bin/fez"
+  '';
+}
diff --git a/pkgs/games/humblebundle/ftl.nix b/pkgs/games/humblebundle/ftl.nix
new file mode 100644
index 00000000..7423951a
--- /dev/null
+++ b/pkgs/games/humblebundle/ftl.nix
@@ -0,0 +1,38 @@
+{ stdenv, fetchHumbleBundle, makeWrapper, SDL, mesa, libdevil, freetype }:
+
+stdenv.mkDerivation rec {
+  name = "ftl-${version}";
+  version = "1.5.13";
+
+  src = fetchHumbleBundle {
+    machineName = "ftlfasterthanlight_soundtrack_linux";
+    downloadName = ".tar.gz";
+    suffix = "tar.gz";
+    md5 = "791e0bc8de73fcdcd5f461a4548ea2d8";
+  };
+
+  buildInputs = [ makeWrapper ];
+
+  patchPhase = let
+    rpath = stdenv.lib.makeLibraryPath [
+      SDL "$out" stdenv.cc.cc mesa libdevil freetype
+    ];
+  in ''
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${rpath}" data/amd64/bin/FTL
+  '';
+
+  installPhase = ''
+    install -vD "data/amd64/bin/FTL" "$out/libexec/ftl/FTL"
+    install -vD "data/amd64/lib/libbass.so" "$out/lib/libbass.so"
+    install -vD "data/amd64/lib/libbassmix.so" "$out/lib/libbassmix.so"
+
+    mkdir -p "$out/bin" "$out/share/ftl"
+    cp -vrt "$out/share/ftl" data/resources
+    makeWrapper "$out/libexec/ftl/FTL" "$out/bin/ftl" \
+      --run "cd '$out/share/ftl'"
+  '';
+
+  dontStrip = true;
+}
diff --git a/pkgs/games/humblebundle/guacamelee.nix b/pkgs/games/humblebundle/guacamelee.nix
new file mode 100644
index 00000000..537ec945
--- /dev/null
+++ b/pkgs/games/humblebundle/guacamelee.nix
@@ -0,0 +1,61 @@
+{ stdenv, fetchHumbleBundle, unzip, SDL2, mesa, writeText, makeWrapper }:
+
+stdenv.mkDerivation rec {
+  name = "guacamelee-${version}";
+  version = "1393037377";
+
+  src = fetchHumbleBundle {
+    machineName = "guacamelee_goldedition_linux";
+    suffix = "sh";
+    md5 = "b06af932c1aaefb8f157c977061388ef";
+  };
+
+  unpackCmd = ''
+    ${unzip}/bin/unzip "$src" 'data/*' || :
+  '';
+
+  preloader = writeText "guacamelee-preloader.c" ''
+    #define _GNU_SOURCE
+    #include <dlfcn.h>
+
+    int chdir(const char *path) {
+      int (*_chdir) (const char *) = dlsym(RTLD_NEXT, "chdir");
+      return _chdir(DATA);
+    }
+  '';
+
+  buildInputs = [ makeWrapper ];
+
+  buildPhase = let
+    rpath = stdenv.lib.makeLibraryPath [ SDL2 stdenv.cc.cc mesa ];
+    fmodRpath = stdenv.lib.makeLibraryPath [ stdenv.cc.cc ];
+  in ''
+    gcc -Werror -shared "$preloader" -o preloader.so -ldl \
+      -DDATA=\"$out/share/guacamelee\"
+
+    for i in libfmodevent-4.44.27.so libfmodex-4.44.27.so; do
+      patchelf --set-rpath "${fmodRpath}:$out/libexec/guacamelee" \
+        "x86/lib32/$i"
+    done
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${rpath}:$out/libexec/guacamelee" x86/game-bin
+  '';
+
+  installPhase = ''
+    install -vD x86/game-bin "$out/libexec/guacamelee/guacamelee"
+    install -vD preloader.so "$out/libexec/guacamelee/preloader.so"
+
+    makeWrapper "$out/libexec/guacamelee/guacamelee" "$out/bin/guacamelee" \
+      --set LD_PRELOAD "$out/libexec/guacamelee/preloader.so"
+
+    for i in libfmodevent-4.44.27.so libfmodex-4.44.27.so; do
+      install -vD "x86/lib32/$i" "$out/libexec/guacamelee/$i"
+    done
+
+    mkdir -p "$out/share"
+    cp -vRd noarch "$out/share/guacamelee"
+  '';
+
+  dontStrip = true;
+}
diff --git a/pkgs/games/humblebundle/hammerwatch.nix b/pkgs/games/humblebundle/hammerwatch.nix
new file mode 100644
index 00000000..8cf65211
--- /dev/null
+++ b/pkgs/games/humblebundle/hammerwatch.nix
@@ -0,0 +1,40 @@
+{ stdenv, fetchHumbleBundle, makeWrapper, unzip, mono, SDL2, mesa, openal
+, pulseaudio
+}:
+
+# FIXME: Dosn't support the XDG Base Directory Specification,
+#        so enforce it using LD_PRELOAD maybe?
+
+stdenv.mkDerivation rec {
+  name = "hammerwatch-${version}";
+  version = "1.3";
+
+  src = fetchHumbleBundle {
+    machineName = "hammerwatch_linux";
+    suffix = "zip";
+    md5 = "7cd77e4395f394c3062322c96e418732";
+  };
+
+  buildInputs = [ unzip makeWrapper ];
+
+  installPhase = let
+    rpath = stdenv.lib.makeLibraryPath [ SDL2 mesa openal pulseaudio ];
+    monoNoLLVM = mono.override { withLLVM = false; };
+  in ''
+    mkdir -p "$out/lib"
+    cp -rt "$out/lib" SDL2-CS.dll SDL2-CS.dll.config \
+      TiltedEngine.dll Lidgren.Network.dll FarseerPhysicsOTK.dll \
+      ICSharpCode.SharpZipLib.dll SteamworksManaged.dll NVorbis.dll
+
+    libexec="$out/libexec/hammerwatch"
+    install -vD Hammerwatch.exe "$libexec/hammerwatch.exe"
+    cp -rt "$libexec" assets.bin editor levels
+
+    makeWrapper "${monoNoLLVM}/bin/mono" "$out/bin/hammerwatch" \
+      --add-flags "$libexec/hammerwatch.exe" \
+      --set MONO_PATH "$out/lib" \
+      --set LD_LIBRARY_PATH "${rpath}"
+  '';
+
+  dontStrip = true;
+}
diff --git a/pkgs/games/humblebundle/jamestown.nix b/pkgs/games/humblebundle/jamestown.nix
new file mode 100644
index 00000000..15900bba
--- /dev/null
+++ b/pkgs/games/humblebundle/jamestown.nix
@@ -0,0 +1,55 @@
+{ stdenv, fetchHumbleBundle, unzip, pkgsi686Linux, expect, makeWrapper
+, SDL, openal
+}:
+
+let
+  version = "1.0.2";
+  usVersion = stdenv.lib.replaceChars ["."] ["_"] version;
+in stdenv.mkDerivation rec {
+  name = "jamestown-${version}";
+
+  src = fetchHumbleBundle {
+    machineName = "jamestown_linux";
+    downloadName = ".zip";
+    suffix = "zip";
+    md5 = "dcfb4348aba89f0f26bf5b4c7e05d936";
+  };
+
+  buildInputs = [ makeWrapper ];
+
+  unpackPhase = ''
+    ${unzip}/bin/unzip -q "$src"
+    patchelf --set-interpreter "${pkgsi686Linux.glibc}"/lib/ld-linux.so.* \
+      "JamestownInstaller_${usVersion}-bin"
+    ${expect}/bin/expect <<INSTALL
+    spawn "./JamestownInstaller_${usVersion}-bin"
+    expect "see more?"
+    send "n\r"
+    expect "Accept this license?"
+    send "y\r"
+    expect "Press enter to continue."
+    send "\r"
+    expect "Enter path"
+    send "$(pwd)/${name}\r"
+    expect eof
+    INSTALL
+    sourceRoot="$(pwd)/${name}"
+  '';
+
+  installPhase = let
+    rpath = stdenv.lib.makeLibraryPath [ SDL openal ];
+  in ''
+    libexec="$out/libexec/jamestown"
+    install -vD Jamestown-amd64 "$libexec/jamestown"
+
+    mkdir -p "$out/share"
+    mv Archives "$out/share/jamestown"
+
+    makeWrapper "$(cat "$NIX_CC/nix-support/dynamic-linker")" \
+      "$out/bin/jamestown" \
+      --add-flags "$libexec/jamestown" \
+      --set LD_LIBRARY_PATH "${rpath}"
+
+    false # Both amd64 and i686 binaries are fucking BROKEN, wait for 1.0.3...
+  '';
+}
diff --git a/pkgs/games/humblebundle/liads.nix b/pkgs/games/humblebundle/liads.nix
new file mode 100644
index 00000000..a96af8e0
--- /dev/null
+++ b/pkgs/games/humblebundle/liads.nix
@@ -0,0 +1,43 @@
+{ stdenv, fetchHumbleBundle, unzip, mesa, xorg, libpulseaudio }:
+
+stdenv.mkDerivation rec {
+  name = "liads-${version}";
+  version = "20160121";
+
+  src = fetchHumbleBundle {
+    machineName = "loversinadangerousspacetime_linux";
+    suffix = "zip";
+    md5 = "0d81adb63ca9233165fb5de415fa5963";
+  };
+
+  unpackCmd = ''
+    ${unzip}/bin/unzip -qq -d liads "$src" || :
+  '';
+
+  arch = if stdenv.system == "x86_64-linux" then "x86_64" else "x86";
+  executable = "LoversInADangerousSpacetime.${arch}";
+
+  buildPhase = let
+    rpath = stdenv.lib.makeLibraryPath [
+      stdenv.cc.cc mesa xorg.libX11 xorg.libXcursor xorg.libXrandr libpulseaudio
+    ];
+  in ''
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${rpath}" "$executable"
+  '';
+
+  installPhase = ''
+    install -vD "$executable" "$out/libexec/liads/liads"
+    ln -s "$out/share/liads" "$out/libexec/liads/Data"
+
+    mkdir -p "$out/bin"
+    ln -s "$out/libexec/liads/liads" "$out/bin/liads"
+
+    mkdir -p "$out/share"
+    cp -vRd LoversInADangerousSpacetime_Data "$out/share/liads"
+  '';
+
+  dontStrip = true;
+  dontPatchELF = true;
+}
diff --git a/pkgs/games/humblebundle/megabytepunch.nix b/pkgs/games/humblebundle/megabytepunch.nix
new file mode 100644
index 00000000..643e5835
--- /dev/null
+++ b/pkgs/games/humblebundle/megabytepunch.nix
@@ -0,0 +1,18 @@
+{ stdenv, fetchHumbleBundle }:
+
+stdenv.mkDerivation rec {
+  name = "megabytepunch-${version}";
+  version = "1.12";
+
+  src = fetchHumbleBundle {
+    machineName = "megabytepunch_linux";
+    suffix = "tar.gz";
+    md5 = "13487ae35c99817ce5f19b45fa51158b";
+  };
+
+  patchPhase = ''
+    patchelf \
+      --set-interpreter "$(cat $NIX_GCC/nix-support/dynamic-linker)" \
+
+  '';
+}
diff --git a/pkgs/games/humblebundle/rocketbirds.nix b/pkgs/games/humblebundle/rocketbirds.nix
new file mode 100644
index 00000000..a57d1562
--- /dev/null
+++ b/pkgs/games/humblebundle/rocketbirds.nix
@@ -0,0 +1,11 @@
+{ stdenv, fetchHumbleBundle }:
+
+stdenv.mkDerivation rec {
+  name = "rocketbirds-${version}";
+  version = "20130917";
+
+  src = fetchHumbleBundle {
+    name = "Rocketbirds${version}.sh";
+    md5 = "7c5e6da4cd7fc7f2f51861f8b96a386f";
+  };
+}
diff --git a/pkgs/games/humblebundle/spaz.nix b/pkgs/games/humblebundle/spaz.nix
new file mode 100644
index 00000000..5e40ea49
--- /dev/null
+++ b/pkgs/games/humblebundle/spaz.nix
@@ -0,0 +1,39 @@
+{ stdenv, fetchHumbleBundle, unzip, pkgsi686Linux }:
+
+stdenv.mkDerivation rec {
+  name = "spaz-${version}";
+  version = "09182012";
+
+  src = fetchHumbleBundle {
+    name = "spaz-linux-humblebundle-${version}-bin";
+    md5 = "9b2f28009949f2dff9f3a737e46fabfd";
+  };
+
+  buildInputs = [ pkgsi686Linux.makeWrapper ];
+
+  unpackCmd = ''
+    ${unzip}/bin/unzip -qq "$src" 'data/*' || true
+  '';
+
+  dontStrip = true;
+
+  buildPhase = let
+    libs = pkgsi686Linux.stdenv.lib.makeLibraryPath [
+      pkgsi686Linux.stdenv.cc.cc pkgsi686Linux.SDL
+    ];
+  in ''
+    patchelf --set-interpreter "${pkgsi686Linux.glibc}"/lib/ld-linux.so.* \
+             --set-rpath "${libs}" SPAZ
+  '';
+
+  installPhase = let
+    libs = pkgsi686Linux.stdenv.lib.makeLibraryPath [
+      pkgsi686Linux.mesa pkgsi686Linux.openal pkgsi686Linux.alsaPlugins
+    ];
+  in ''
+    install -vD SPAZ "$out/libexec/spaz/spaz"
+    cp -rt "$out/libexec/spaz" audio.so common game mods
+    makeWrapper "$out/libexec/spaz/spaz" "$out/bin/spaz" \
+      --set LD_LIBRARY_PATH "${libs}"
+  '';
+}
diff --git a/pkgs/games/humblebundle/swordsandsoldiers.nix b/pkgs/games/humblebundle/swordsandsoldiers.nix
new file mode 100644
index 00000000..2fd4fc4b
--- /dev/null
+++ b/pkgs/games/humblebundle/swordsandsoldiers.nix
@@ -0,0 +1,43 @@
+{ stdenv, fetchHumbleBundle, makeWrapper
+, SDL, mesa, zlib, openal, libvorbis, xorg, fontconfig, freetype, libogg
+}:
+
+stdenv.mkDerivation rec {
+  name = "swordsandsoldiers-${version}";
+  version = "20120325";
+
+  src = fetchHumbleBundle {
+    machineName = "swordsandsoldiers_android_and_pc_linux";
+    downloadName = "x86_64.tar.gz";
+    suffix = "tar.gz";
+    md5 = "5f0c9789fa053cbf6bac021a338245bb";
+  };
+
+  buildInputs = [ makeWrapper ];
+
+  patchPhase = let
+    rpath = stdenv.lib.makeLibraryPath [
+      SDL mesa zlib openal libvorbis fontconfig freetype stdenv.cc.cc libogg
+      xorg.libX11 xorg.libXft xorg.libXinerama xorg.libXext xorg.libXpm
+    ];
+  in ''
+    for i in SwordsAndSoldiers.bin SwordsAndSoldiersSetup.bin; do
+      patchelf \
+        --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+        --set-rpath "${rpath}" "$i"
+    done
+  '';
+
+  installPhase = ''
+    libexec="$out/libexec/swordsandsoldiers"
+    install -vD SwordsAndSoldiers.bin "$libexec/swordsandsoldiers"
+    install -vD SwordsAndSoldiersSetup.bin "$libexec/setup"
+    mv Data "$libexec/"
+
+    mkdir -p "$out/bin"
+    ln -s "$libexec/swordsandsoldiers" "$out/bin/swordsandsoldiers"
+    ln -s "$libexec/setup" "$out/bin/swordsandsoldiers-setup"
+  '';
+
+  dontStrip = true;
+}
diff --git a/pkgs/games/humblebundle/unepic.nix b/pkgs/games/humblebundle/unepic.nix
new file mode 100644
index 00000000..cc4099f5
--- /dev/null
+++ b/pkgs/games/humblebundle/unepic.nix
@@ -0,0 +1,44 @@
+{ stdenv, fetchHumbleBundle, unzip, makeWrapper, SDL2, SDL2_mixer, zlib }:
+
+let
+  version = "1.50.5";
+  versionName = "15005";
+  arch = { 
+    "i686-linux" = "32";
+    "x86_64-linux" = "64";
+  }.${stdenv.system};
+in stdenv.mkDerivation rec {
+  name = "unepic-${version}";
+
+  src = fetchHumbleBundle {
+    name = "unepic-15005.run";
+    machineName = "unepic_linux";
+    downloadName = ".run";
+    md5 = "940824c4de6e48522845f63423e87783";
+  };
+
+  phases = [ "installPhase" ];
+
+  buildInputs = [ unzip makeWrapper ];
+
+  installPhase = let
+    rpath = stdenv.lib.makeLibraryPath [ SDL2 SDL2_mixer zlib stdenv.cc.cc ];
+  in ''
+    dest="$out/opt/games/unepic"
+    exe="$dest/unepic${arch}"
+
+    mkdir -p "$out/opt/games"
+    unzip "$src" "data/*" -d "$out/opt/games" || [ "$?" -eq 1 ]
+    mv "$out/opt/games/data" "$dest"
+    rm -r "$dest"/lib*
+
+    # Patch $exe acccording to arch.
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${rpath}" "$exe"
+
+    mkdir -p "$out/bin"
+
+    makeWrapper "$exe" "$out/bin/unepic" --run "cd '$dest'"
+  '';
+}
diff --git a/pkgs/games/steam/default.nix b/pkgs/games/steam/default.nix
new file mode 100644
index 00000000..03e6b180
--- /dev/null
+++ b/pkgs/games/steam/default.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.steam;
+
+  self = rec {
+    callPackage = pkgs.lib.callPackageWith (pkgs // self);
+
+    fetchSteam = callPackage ./fetchsteam {
+      inherit (config.steam) username password;
+    };
+
+    starbound = callPackage ./starbound.nix { flavor = "stable"; };
+    starbound-unstable = callPackage ./starbound.nix { flavor = "unstable"; };
+  };
+in with lib; {
+  options.steam = {
+    username = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        User name for your Steam account.
+      '';
+    };
+
+    password = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        Password for your Steam account.
+      '';
+    };
+  };
+
+  config.packages = {
+    steam = mkIf (cfg.username != null && cfg.password != null) self;
+  };
+}
diff --git a/pkgs/games/steam/fetchsteam/default.nix b/pkgs/games/steam/fetchsteam/default.nix
new file mode 100644
index 00000000..cccddb51
--- /dev/null
+++ b/pkgs/games/steam/fetchsteam/default.nix
@@ -0,0 +1,91 @@
+{ stdenv, runCommand, writeText, fetchFromGitHub, buildDotnetPackage
+, username, password
+}:
+
+{ name, appId, depotId, manifestId, sha256, fileList ? [] }:
+
+let
+  protobuf-net = buildDotnetPackage rec {
+    baseName = "protobuf-net";
+    version = "2.0.0.668";
+
+    src = fetchFromGitHub {
+      owner = "mgravell";
+      repo = "protobuf-net";
+      rev = "r668";
+      sha256 = "1060pihqkbr9pd2z6m01d6fsbc9nj56m6y5a0pch9mqdmviv4896";
+    };
+
+    sourceRoot = "${src.name}/${baseName}";
+  };
+
+  SteamKit2 = buildDotnetPackage rec {
+    baseName = "SteamKit2";
+    version = "1.6.4";
+
+    src = fetchFromGitHub {
+      owner = "SteamRE";
+      repo = "SteamKit";
+      rev = "SteamKit_${version}";
+      sha256 = "17d7wi2f396qhp4w9sf37lazvsaqws8x071hfis9gv5llv6s7q46";
+    };
+
+    buildInputs = [ protobuf-net ];
+
+    xBuildFiles = [ "SteamKit2/SteamKit2.sln" ];
+    outputFiles = [ "SteamKit2/SteamKit2/bin/Release/*" ];
+  };
+
+  DepotDownloader = buildDotnetPackage rec {
+    baseName = "DepotDownloader";
+    version = "2.1.1git20160207";
+
+    src = fetchFromGitHub {
+      owner = "SteamRE";
+      repo = baseName;
+      rev = "5fa6621d9f9448fcd20c974b427a8bd2cb044cb4";
+      sha256 = "0vb566d7x1scd96c8ybq6gdbc2cv5jjq453ld458qcvfy587amfn";
+    };
+
+    patches = [ ./downloader.patch ];
+
+    postPatch = ''
+      sed -i \
+        -e 's/\(<[Rr]eference *[Ii]nclude="[^", ]\+\)[^"]*/\1/g' \
+        -e 's,<[Ss]pecific[Vv]ersion>[Tt]rue</[Ss]pecific[Vv]ersion>,,g' \
+        DepotDownloader/DepotDownloader.csproj
+      sed -i -e 's/ version="[^"]*"//g' DepotDownloader/packages.config
+    '';
+
+    buildInputs = [ SteamKit2 protobuf-net ];
+
+    outputFiles = [ "${baseName}/bin/Release/*" ];
+
+    # UUUGLY, but I don't want to spend a week trying to get this working
+    # without that nasty wrapper.
+    makeWrapperArgs = let
+      mkMono = name: path: "${path}/lib/dotnet/${name}";
+      paths = stdenv.lib.mapAttrsToList mkMono {
+        inherit SteamKit2 protobuf-net;
+      };
+      monoPath = stdenv.lib.concatStringsSep ":" paths;
+    in [ "--prefix MONO_PATH : \"${monoPath}\"" ];
+  };
+
+  fileListFile = let
+    content = stdenv.lib.concatStringsSep "\n" fileList;
+  in writeText "steam-file-list-${name}.txt" content;
+
+in with stdenv.lib; runCommand "${name}-src" {
+  buildInputs = [ DepotDownloader ];
+  inherit username password appId depotId manifestId;
+  outputHashAlgo = "sha256";
+  outputHash = sha256;
+  outputHashMode = "recursive";
+} ''
+  depotdownloader -app "$appId" -depot "$depotId" -manifest "$manifestId" \
+    ${optionalString (fileList != []) "-filelist \"${fileListFile}\""} \
+    -username "$username" -password "$password" -dir "$out"
+  rm -r "$out/.DepotDownloader"
+  rm "$out/_steam_depot_manifest_$depotId.csv"
+''
diff --git a/pkgs/games/steam/fetchsteam/downloader.patch b/pkgs/games/steam/fetchsteam/downloader.patch
new file mode 100644
index 00000000..72e5c473
--- /dev/null
+++ b/pkgs/games/steam/fetchsteam/downloader.patch
@@ -0,0 +1,34 @@
+diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs
+index 21c317e..81f2a93 100644
+--- a/DepotDownloader/ContentDownloader.cs
++++ b/DepotDownloader/ContentDownloader.cs
+@@ -34,7 +34,7 @@ namespace DepotDownloader
+             public string installDir { get; private set; }
+             public string contentName { get; private set; }
+ 
+-            public ulong manifestId { get; private set; }
++            public ulong manifestId { get; set; }
+             public byte[] depotKey;
+ 
+             public DepotDownloadInfo(uint depotid, ulong manifestId, string installDir, string contentName)
+@@ -198,9 +198,6 @@ namespace DepotDownloader
+ 
+         static ulong GetSteam3DepotManifest(uint depotId, uint appId, string branch)
+         {
+-            if (Config.ManifestId != INVALID_MANIFEST_ID)
+-                return Config.ManifestId;
+-
+             KeyValue depots = GetSteam3AppSection(appId, EAppInfoSection.Depots);
+             KeyValue depotChild = depots[depotId.ToString()];
+ 
+@@ -583,6 +580,10 @@ namespace DepotDownloader
+                 ConfigStore.TheConfig.LastManifests[depot.id] = INVALID_MANIFEST_ID;
+                 ConfigStore.Save();
+ 
++                Console.WriteLine("Latest manifest ID is {0}.", depot.manifestId);
++                if (Config.ManifestId != INVALID_MANIFEST_ID)
++                    depot.manifestId = Config.ManifestId;
++
+                 if (lastManifestId != INVALID_MANIFEST_ID)
+                 {
+                     var oldManifestFileName = Path.Combine(configDir, string.Format("{0}.bin", lastManifestId));
diff --git a/pkgs/games/steam/starbound.nix b/pkgs/games/steam/starbound.nix
new file mode 100644
index 00000000..ba63fcfa
--- /dev/null
+++ b/pkgs/games/steam/starbound.nix
@@ -0,0 +1,132 @@
+{ stdenv, fetchSteam, makeWrapper, SDL, mesa, flavor ? "stable" }:
+
+let
+  renameAttrs = f: let
+    rename = name: value: {
+      name = f name;
+      inherit value;
+    };
+  in stdenv.lib.mapAttrs' rename;
+
+  darwinize = renameAttrs (bin: "Starbound.app/Contents/MacOS/${bin}");
+  winize = renameAttrs (bin: "${bin}.exe");
+
+  mkOsBinaryDeps = with stdenv.lib;
+    if stdenv.system == "x86_64-darwin" then darwinize
+    else if elem stdenv.system [ "i686-cygwin" "x86_64-cygwin" ] then winize
+    else id;
+
+  binaryDeps = mkOsBinaryDeps {
+    starbound.deps = [ SDL mesa ];
+    starbound_server.name = "starbound-server";
+    asset_packer.name = "starbound-asset-packer";
+    asset_unpacker.name = "starbound-asset-unpacker";
+    dump_versioned_json.name = "starbound-dump-versioned-json";
+    make_versioned_json.name = "starbound-make-versioned-json";
+    planet_mapgen.name = "starbound-planet-mapgen";
+  };
+
+  binpath = if stdenv.system == "x86_64-linux" then "linux64"
+            else if stdenv.system == "i686-linux" then "linux32"
+            else if stdenv.system == "x86_64-darwin" then "osx"
+            else if stdenv.system == "i686-cygwin" then "win32"
+            else if stdenv.system == "x86_64-cygwin" then "win64"
+            else throw "Unsupported system ${stdenv.system} for Starbound";
+
+  upstream = let
+    attrs = if flavor == "stable" then {
+      name = "starbound";
+      appId = 211820;
+      depotId = 211821;
+      manifestId = 1842730272313189605;
+      sha256 = "0qppfn56c778wsg38hi6sxgi3rl9nv72h9rmmxybi1vzpf3p49py";
+    } else if flavor == "unstable" then {
+      name = "starbound-unstable";
+      appId = 367540;
+      depotId = 367541;
+      manifestId = 6970641909803280413;
+      sha256 = "0qppfn56c778wsg38hi6sxgi3rl9nv72h9rmmxybi1vzpf3p49py";
+    } else throw "Unsupported flavor, use either `stable' or `unstable'.";
+  in fetchSteam (attrs // {
+    fileList = [
+      "^(?:assets|tiled)/"
+      ( "^${binpath}(?:/Starbound\\.app/Contents/MacOS)?"
+      + "/(?:[a-zA-Z0-9_-]+(?:\\.exe)?|sbboot\\.config)$")
+    ];
+  });
+
+in stdenv.mkDerivation {
+  name = "${upstream.name}-20160208";
+
+  unpackPhase = ":";
+
+  configurePhase = ''
+    libexec="$out/libexec/starbound"
+    data="$out/share/starbound"
+  '';
+
+  inherit binpath upstream;
+
+  buildInputs = [ makeWrapper ];
+
+  buildPhase = with stdenv.lib; ''
+    mkdir -p patched
+    sed -e 's,\.\./assets,'"$data/assets"',g' \
+        -e 's,\.\./giraffe_storage,.,g' \
+        "$upstream/$binpath/sbboot.config" > "patched/sbboot.config"
+  '' + concatStrings (mapAttrsToList (bin: attrs: ''
+    mkdir -p "patched/$(dirname "${bin}")"
+    cp -t "patched/$(dirname "${bin}")" "$upstream/$binpath/${bin}"
+    chmod +x "patched/$(basename "${bin}")"
+    patchelf \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${stdenv.lib.makeLibraryPath (attrs.deps or [])}" \
+      "patched/$(basename "${bin}")"
+    if ldd "patched/$(basename "${bin}")" | grep -F 'not found'; then
+      exit 1;
+    fi
+  '') binaryDeps);
+
+  doCheck = true;
+
+  checkPhase = ''
+    checkFailed=
+    for i in "$upstream/$binpath"/*; do
+      [ -f "$i" ] || continue
+      [ "$(basename "$i")" != launcher ] || continue
+      [ ! -e "patched/$(basename "$i")" ] || continue
+
+      echo "Found missing binary $i from the upstream tree."
+      checkFailed=1
+    done
+    [ -z "$checkFailed" ]
+  '';
+
+  installPhase = ''
+    mkdir -p "$out/bin"
+    ${stdenv.lib.concatStrings (stdenv.lib.mapAttrsToList (bin: attrs: ''
+      prog="$(basename "${bin}")"
+      install -vD "patched/$prog" "$libexec/$prog"
+      cat > "$out/bin/${attrs.name or "$prog"}" <<EOF
+      #!${stdenv.shell} -e
+      [ -n "\$XDG_DATA_HOME" ] || XDG_DATA_HOME="\$HOME/.local/share"
+      mkdir -p "\$XDG_DATA_HOME/starbound/mods"
+      ln -sf "$out/etc/sbboot.config" "\$XDG_DATA_HOME/starbound/sbboot.config"
+      cd "\$XDG_DATA_HOME/starbound"
+      exec "$libexec/$prog" "\$@"
+      EOF
+      chmod +x "$out/bin/${attrs.name or "$prog"}"
+    '') binaryDeps)}
+
+    install -vD -m 644 patched/sbboot.config "$out/etc/sbboot.config"
+
+    mkdir -p "$data"
+    for i in assets tiled; do
+      echo -n "Installing $i..."
+      cp -rt "$data" "$upstream/$i"
+      echo " done."
+    done
+  '';
+
+  dontStrip = true;
+}