23 , versionsJson ? ./versions.json
25 , token ? "" # get/reset token at https://factorio.com/profile
26 , experimental ? false # true means to always use the latest branch
30 assert releaseType == "alpha"
31 || releaseType == "headless"
32 || releaseType == "demo";
36 inherit (lib) importJSON;
38 mods = args.mods or [ ];
43 Please ensure you have set the username and token with config.nix, or
44 /etc/nix/nixpkgs-config.nix if on NixOS.
46 Your token can be seen at https://factorio.com/profile (after logging in). It is
47 not as sensitive as your password, but should still be safeguarded. There is a
48 link on that page to revoke/invalidate the token, if you believe it has been
49 leaked or wish to take precautions.
53 packageOverrides = pkgs: {
54 factorio = pkgs.factorio.override {
55 username = "FactorioPlayer1654";
56 token = "d5ad5a8971267c895c0da598688761";
61 Alternatively, instead of providing the username+token, you may manually
62 download the release through https://factorio.com/download , then add it to
67 nix-prefetch-url file://\''$HOME/Downloads/factorio_\''${releaseType}_x64_\''${version}.tar.xz --name factorio_\''${releaseType}_x64-\''${version}.tar.xz
69 Note the ultimate "_" is replaced with "-" in the --name arg!
72 desktopItem = makeDesktopItem {
74 desktopName = "Factorio";
75 comment = "A game in which you build and maintain factories.";
78 categories = [ "Game" ];
81 branch = if experimental then "experimental" else "stable";
83 # NB `experimental` directs us to take the latest build, regardless of its branch;
84 # hence the (stable, experimental) pairs may sometimes refer to the same distributable.
85 versions = importJSON versionsJson;
86 binDists = makeBinDists versions;
88 actual = binDists.${stdenv.hostPlatform.system}.${releaseType}.${branch} or (throw "Factorio ${releaseType}-${branch} binaries for ${stdenv.hostPlatform.system} are not available for download.");
90 makeBinDists = versions:
92 f = path: name: value:
93 if builtins.isAttrs value then
94 if value ? "name" then
97 builtins.mapAttrs (f (path ++ [ name ])) value
99 throw "expected attrset at ${toString path} - got ${toString value}";
101 builtins.mapAttrs (f [ ]) versions;
102 makeBinDist = { name, version, tarDirectory, url, sha256, needsAuth }: {
103 inherit version tarDirectory;
106 fetchurl { inherit name url sha256; }
108 (lib.overrideDerivation
110 inherit name url sha256;
120 # This preHook hides the credentials from /proc
122 if username != "" && token != "" then ''
123 echo -n "${username}" >username
124 echo -n "${token}" >token
126 # Deliberately failing since username/token was not provided, so we can't fetch.
127 # We can't use builtins.throw since we want the result to be used if the tar is in the store already.
139 use-system-read-write-data-directories=false
141 read-data=$out/share/factorio/data/
148 if [[ -e ~/.factorio/config.cfg ]]; then
149 # Config file exists, but may have wrong path.
150 # Try to edit it. I'm sure this is perfectly safe and will never go wrong.
151 sed -i 's|^read-data=.*|read-data=$out/share/factorio/data/|' ~/.factorio/config.cfg
153 # Config file does not exist. Phew.
154 install -D $out/share/factorio/config-base.cfg ~/.factorio/config.cfg
158 modDir = factorio-utils.mkModDirDrv mods mods-dat;
160 base = with actual; {
161 pname = "factorio-${releaseType}";
164 preferLocalBuild = true;
168 mkdir -p $out/{bin,share/factorio}
169 cp -a data $out/share/factorio
170 cp -a bin/${tarDirectory}/factorio $out/bin/factorio
172 --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
176 passthru.updateScript =
177 if (username != "" && token != "") then [
179 "--username=${username}"
184 description = "A game in which you build and maintain factories";
186 Factorio is a game in which you build and maintain factories.
188 You will be mining resources, researching technologies, building
189 infrastructure, automating production and fighting enemies. Use your
190 imagination to design your factory, combine simple elements into
191 ingenious structures, apply management skills to keep it working and
192 finally protect it from the creatures who don't really like you.
194 Factorio has been in development since spring of 2012, and reached
195 version 1.0 in mid 2020.
197 homepage = "https://www.factorio.com/";
198 sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
199 license = lib.licenses.unfree;
200 maintainers = with lib.maintainers; [ Baughn elitak erictapen priegger lukegb ];
201 platforms = [ "x86_64-linux" ];
209 nativeBuildInputs = [ makeWrapper ];
210 buildInputs = [ libpulseaudio ];
212 libPath = lib.makeLibraryPath [
228 installPhase = base.installPhase + ''
229 wrapProgram $out/bin/factorio \
230 --prefix LD_LIBRARY_PATH : /run/opengl-driver/lib:$libPath \
231 --run "$out/share/factorio/update-config.sh" \
233 --add-flags "-c \$HOME/.factorio/config.cfg" \
234 ${lib.optionalString (mods!=[]) "--add-flags --mod-directory=${modDir}"}
236 # TODO Currently, every time a mod is changed/added/removed using the
237 # modlist, a new derivation will take up the entire footprint of the
238 # client. The only way to avoid this is to remove the mods arg from the
239 # package function. The modsDir derivation will have to be built
240 # separately and have the user specify it in the .factorio config or
241 # right along side it using a symlink into the store I think i will
242 # just remove mods for the client derivation entirely. this is much
243 # cleaner and more useful for headless mode.
245 # TODO: trying to toggle off a mod will result in read-only-fs-error.
246 # not much we can do about that except warn the user somewhere. In
247 # fact, no exit will be clean, since this error will happen on close
248 # regardless. just prints an ugly stacktrace but seems to be otherwise
249 # harmless, unless maybe the user forgets and tries to use the mod
252 install -m0644 <(cat << EOF
255 ) $out/share/factorio/config-base.cfg
257 install -m0755 <(cat << EOF
260 ) $out/share/factorio/update-config.sh
262 mkdir -p $out/share/icons/hicolor/{64x64,128x128}/apps
263 cp -a data/core/graphics/factorio-icon.png $out/share/icons/hicolor/64x64/apps/factorio.png
264 cp -a data/core/graphics/factorio-icon@2x.png $out/share/icons/hicolor/128x128/apps/factorio.png
265 ln -s ${desktopItem}/share/applications $out/share/
270 installPhase = demo.installPhase + ''
271 cp -a doc-html $out/share/factorio
277 stdenv.mkDerivation (releases.${releaseType})