nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 308 lines 9.7 kB view raw
1{ 2 lib, 3 alsa-lib, 4 factorio-utils, 5 fetchurl, 6 libGL, 7 libICE, 8 libSM, 9 libX11, 10 libXcursor, 11 libXext, 12 libXi, 13 libXinerama, 14 libXrandr, 15 libpulseaudio, 16 libxkbcommon, 17 makeDesktopItem, 18 makeWrapper, 19 releaseType ? "alpha", 20 stdenv, 21 wayland, 22 23 mods-dat ? null, 24 versionsJson ? ./versions.json, 25 username ? "", 26 token ? "", # get/reset token at https://factorio.com/profile 27 experimental ? false, # true means to always use the latest branch 28 ... 29}@args: 30 31assert 32 releaseType == "alpha" 33 || releaseType == "headless" 34 || releaseType == "demo" 35 || releaseType == "expansion"; 36 37let 38 39 inherit (lib) importJSON; 40 41 mods = args.mods or [ ]; 42 43 helpMsg = 44 { dlName, storeName }: 45 '' 46 47 ===FETCH FAILED=== 48 Please ensure you have set the username and token with config.nix, or 49 /etc/nix/nixpkgs-config.nix if on NixOS. 50 51 Your token can be seen at https://factorio.com/profile (after logging in). 52 Beware this will add the credentials to the Nix store, which is 53 world-readable on the local machine. It is not as sensitive as your 54 password, but should still be safeguarded. There is a link on that page to 55 revoke/invalidate the token, if you believe it has been leaked or wish to 56 take precautions. 57 58 Example: 59 { 60 packageOverrides = pkgs: { 61 factorio = pkgs.factorio.override { 62 username = "FactorioPlayer1654"; 63 token = "d5ad5a8971267c895c0da598688761"; 64 }; 65 }; 66 } 67 68 Alternatively, instead of providing the username+token, you may manually 69 download the release through https://factorio.com/download , then add it to 70 the store using e.g.: 71 72 nix-prefetch-url file://\''$HOME/Downloads/${dlName} --name ${storeName} 73 74 If you go this route you might want to tell Nix to explicitly hold on to the 75 source tarball. Otherwise it could get GC'd from the Nix store and you'd 76 have to redownload it next time the package wants to rebuild to use a newer 77 dependency. E.g. if you're using NixOS: 78 79 system.extraDependencies = [ 80 factorio.src 81 ]; 82 ''; 83 84 desktopItem = makeDesktopItem { 85 name = "factorio"; 86 desktopName = "Factorio"; 87 comment = "A game in which you build and maintain factories."; 88 exec = "factorio"; 89 icon = "factorio"; 90 categories = [ "Game" ]; 91 }; 92 93 branch = if experimental then "experimental" else "stable"; 94 95 # NB `experimental` directs us to take the latest build, regardless of its branch; 96 # hence the (stable, experimental) pairs may sometimes refer to the same distributable. 97 versions = importJSON versionsJson; 98 binDists = makeBinDists versions; 99 100 actual = 101 binDists.${stdenv.hostPlatform.system}.${releaseType}.${branch} 102 or (throw "Factorio ${releaseType}-${branch} binaries for ${stdenv.hostPlatform.system} are not available for download."); 103 104 makeBinDists = 105 versions: 106 let 107 f = 108 path: name: value: 109 if builtins.isAttrs value then 110 if value ? "name" then makeBinDist value else builtins.mapAttrs (f (path ++ [ name ])) value 111 else 112 throw "expected attrset at ${toString path} - got ${toString value}"; 113 in 114 builtins.mapAttrs (f [ ]) versions; 115 makeBinDist = 116 { 117 name, 118 version, 119 tarDirectory, 120 url, 121 sha256, 122 needsAuth, 123 candidateHashFilenames ? [ ], 124 }: 125 { 126 inherit version tarDirectory; 127 src = 128 if !needsAuth then 129 fetchurl { inherit name url sha256; } 130 else 131 (lib.overrideDerivation 132 (fetchurl { 133 inherit name url sha256; 134 curlOptsList = [ 135 "--get" 136 "--data-urlencode" 137 "username@username" 138 "--data-urlencode" 139 "token@token" 140 ]; 141 }) 142 (_: { 143 # This preHook hides the credentials from /proc 144 preHook = 145 if username != "" && token != "" then 146 '' 147 echo -n "${username}" >username 148 echo -n "${token}" >token 149 '' 150 else 151 '' 152 # Deliberately failing since username/token was not provided, so we can't fetch. 153 exit 1 154 ''; 155 failureHook = '' 156 cat <<EOF 157 ${helpMsg { 158 dlName = if candidateHashFilenames != [ ] then builtins.head candidateHashFilenames else name; 159 storeName = name; 160 }} 161 EOF 162 ''; 163 }) 164 ); 165 }; 166 167 configBaseCfg = '' 168 use-system-read-write-data-directories=false 169 [path] 170 read-data=$out/share/factorio/data/ 171 [other] 172 check_updates=false 173 ''; 174 175 updateConfigSh = '' 176 #! $SHELL 177 if [[ -e ~/.factorio/config.cfg ]]; then 178 # Config file exists, but may have wrong path. 179 # Try to edit it. I'm sure this is perfectly safe and will never go wrong. 180 sed -i 's|^read-data=.*|read-data=$out/share/factorio/data/|' ~/.factorio/config.cfg 181 else 182 # Config file does not exist. Phew. 183 install -D $out/share/factorio/config-base.cfg ~/.factorio/config.cfg 184 fi 185 ''; 186 187 modDir = factorio-utils.mkModDirDrv mods mods-dat; 188 189 base = with actual; { 190 # remap -expansion to -space-age to better match the attr name in nixpkgs. 191 pname = "factorio-${if releaseType == "expansion" then "space-age" else releaseType}"; 192 inherit version src; 193 194 preferLocalBuild = true; 195 dontBuild = true; 196 197 installPhase = '' 198 mkdir -p $out/{bin,share/factorio} 199 cp -a data $out/share/factorio 200 cp -a bin/${tarDirectory}/factorio $out/bin/factorio 201 patchelf \ 202 --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \ 203 $out/bin/factorio 204 ''; 205 206 passthru.updateScript = ./update.py; 207 208 meta = { 209 description = "Game in which you build and maintain factories"; 210 longDescription = '' 211 Factorio is a game in which you build and maintain factories. 212 213 You will be mining resources, researching technologies, building 214 infrastructure, automating production and fighting enemies. Use your 215 imagination to design your factory, combine simple elements into 216 ingenious structures, apply management skills to keep it working and 217 finally protect it from the creatures who don't really like you. 218 219 Factorio has been in development since spring of 2012, and reached 220 version 1.0 in mid 2020. 221 ''; 222 homepage = "https://www.factorio.com/"; 223 sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; 224 license = lib.licenses.unfree; 225 maintainers = with lib.maintainers; [ 226 Baughn 227 priegger 228 lukegb 229 ]; 230 platforms = [ "x86_64-linux" ]; 231 mainProgram = "factorio"; 232 }; 233 }; 234 235 releases = rec { 236 headless = base; 237 demo = base // { 238 239 nativeBuildInputs = [ makeWrapper ]; 240 buildInputs = [ libpulseaudio ]; 241 242 libPath = lib.makeLibraryPath [ 243 alsa-lib 244 libGL 245 libICE 246 libSM 247 libX11 248 libXcursor 249 libXext 250 libXi 251 libXinerama 252 libXrandr 253 libpulseaudio 254 libxkbcommon 255 wayland 256 ]; 257 258 installPhase = base.installPhase + '' 259 wrapProgram $out/bin/factorio \ 260 --prefix LD_LIBRARY_PATH : /run/opengl-driver/lib:$libPath \ 261 --run "$out/share/factorio/update-config.sh" \ 262 --argv0 "" \ 263 --add-flags "-c \$HOME/.factorio/config.cfg" \ 264 ${lib.optionalString (mods != [ ]) "--add-flags --mod-directory=${modDir}"} 265 266 # TODO Currently, every time a mod is changed/added/removed using the 267 # modlist, a new derivation will take up the entire footprint of the 268 # client. The only way to avoid this is to remove the mods arg from the 269 # package function. The modsDir derivation will have to be built 270 # separately and have the user specify it in the .factorio config or 271 # right along side it using a symlink into the store I think i will 272 # just remove mods for the client derivation entirely. this is much 273 # cleaner and more useful for headless mode. 274 275 # TODO: trying to toggle off a mod will result in read-only-fs-error. 276 # not much we can do about that except warn the user somewhere. In 277 # fact, no exit will be clean, since this error will happen on close 278 # regardless. just prints an ugly stacktrace but seems to be otherwise 279 # harmless, unless maybe the user forgets and tries to use the mod 280 # manager. 281 282 install -m0644 <(cat << EOF 283 ${configBaseCfg} 284 EOF 285 ) $out/share/factorio/config-base.cfg 286 287 install -m0755 <(cat << EOF 288 ${updateConfigSh} 289 EOF 290 ) $out/share/factorio/update-config.sh 291 292 mkdir -p $out/share/icons/hicolor/{64x64,128x128}/apps 293 cp -a data/core/graphics/factorio-icon.png $out/share/icons/hicolor/64x64/apps/factorio.png 294 cp -a data/core/graphics/factorio-icon@2x.png $out/share/icons/hicolor/128x128/apps/factorio.png 295 ln -s ${desktopItem}/share/applications $out/share/ 296 ''; 297 }; 298 alpha = demo // { 299 300 installPhase = demo.installPhase + '' 301 cp -a doc-html $out/share/factorio 302 ''; 303 }; 304 expansion = alpha; 305 }; 306 307in 308stdenv.mkDerivation (releases.${releaseType})