Merge pull request #17479 from elitak/factorio

Factorio: 0.13.8 -> 0.13.13, mod support
This commit is contained in:
Rok Garbas 2016-08-07 04:09:52 +02:00 committed by GitHub
commit a741978f20
5 changed files with 331 additions and 19 deletions

View File

@ -4,14 +4,17 @@ with lib;
let
cfg = config.services.factorio;
factorio = pkgs.factorio-headless;
name = "Factorio";
stateDir = "/var/lib/factorio";
mkSavePath = name: "${stateDir}/saves/${name}.zip";
configFile = pkgs.writeText "factorio.conf" ''
use-system-read-write-data-directories=true
[path]
read-data=${pkgs.factorio-headless}/share/factorio/data
read-data=${factorio}/share/factorio/data
write-data=${stateDir}
'';
modDir = pkgs.factorio-mkModDirDrv cfg.mods;
in
{
options = {
@ -32,7 +35,8 @@ in
description = ''
The name of the savegame that will be used by the server.
When not present in ${stateDir}/saves, it will be generated before starting the service.
When not present in ${stateDir}/saves, a new map with default
settings will be generated before starting the service.
'';
};
# TODO Add more individual settings as nixos-options?
@ -51,6 +55,26 @@ in
customizations.
'';
};
mods = mkOption {
type = types.listOf types.package;
default = [];
description = ''
Mods the server should install and activate.
The derivations in this list must "build" the mod by simply copying
the .zip, named correctly, into the output directory. Eventually,
there will be a way to pull in the most up-to-date list of
derivations via nixos-channel. Until then, this is for experts only.
'';
};
autosave-interval = mkOption {
type = types.nullOr types.int;
default = null;
example = 2;
description = ''
The time, in minutes, between autosaves.
'';
};
};
};
@ -74,12 +98,14 @@ in
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
preStart = ''
test -e ${stateDir}/saves/${cfg.saveName}.zip || \
${pkgs.factorio-headless}/bin/factorio \
--config=${cfg.configFile} \
--create=${stateDir}/saves/${cfg.saveName}.zip
'';
preStart = toString [
"test -e ${stateDir}/saves/${cfg.saveName}.zip"
"||"
"${factorio}/bin/factorio"
"--config=${cfg.configFile}"
"--create=${mkSavePath cfg.saveName}"
(optionalString (cfg.mods != []) "--mod-directory=${modDir}")
];
serviceConfig = {
User = "factorio";
@ -90,10 +116,12 @@ in
PrivateTmp = true;
UMask = "0007";
ExecStart = toString [
"${pkgs.factorio-headless}/bin/factorio"
"${factorio}/bin/factorio"
"--config=${cfg.configFile}"
"--port=${toString cfg.port}"
"--start-server=${stateDir}/saves/${cfg.saveName}.zip"
"--start-server=${mkSavePath cfg.saveName}"
(optionalString (cfg.mods != []) "--mod-directory=${modDir}")
(optionalString (cfg.autosave-interval != null) "--autosave-interval ${toString cfg.autosave-interval}")
];
};
};

View File

@ -1,6 +1,8 @@
{ stdenv, callPackage, fetchurl, makeWrapper
, alsaLib, libX11, libXcursor, libXinerama, libXrandr, libXi, mesa_noglu
, factorio-utils
, releaseType
, mods ? []
, username ? "" , password ? ""
}:
@ -8,7 +10,7 @@ assert releaseType == "alpha" || releaseType == "headless";
with stdenv.lib;
let
version = "0.13.8";
version = "0.13.13";
isHeadless = releaseType == "headless";
arch = if stdenv.system == "x86_64-linux" then {
@ -23,14 +25,14 @@ let
fetch = rec {
url = "https://www.factorio.com/get-download/${version}/${releaseType}/${arch.inUrl}";
name = "factorio_${releaseType}_${arch.inTar}-${version}.tar.gz"; # TODO take this from 302 redirection somehow? fetchurl doesn't help.
name = "factorio_${releaseType}_${arch.inTar}-${version}.tar.gz";
x64 = {
headless = fetchurl { inherit name url; sha256 = "0dliympqnnawfw65n5gnda9mljyqwshmq2hvplf1h8nrp1rw3pgj"; };
alpha = authenticatedFetch { inherit url; sha256 = "12safa8b4g5cpwxbkf8ldkb17lgf33rslr7p81l7gr1lyzfnf82c"; };
headless = fetchurl { inherit name url; sha256 = "1ip0h2kh16s07nk6xqpm0i0yb0x32zn306414j15gqg3j0j0mzpn"; };
alpha = authenticatedFetch { inherit url; sha256 = "1hvj51cggp6cbxyndbl4z07kadzxxk3diiqkkv0jm9s0nrwvq9zr"; };
};
i386 = {
headless = abort "Factorio 32-bit headless binaries are not available for download.";
alpha = authenticatedFetch { inherit url; sha256 = "0m4m183avnqxkw28vb7za14dsmcd01sdldgga0br1clilxmgph2w"; };
alpha = authenticatedFetch { inherit url; sha256 = "14dwlakn7z8jziy0hgm3nskr7chp7753z1dakxlymz9h5653cx8b"; };
};
};
@ -54,14 +56,16 @@ let
fi
'';
modDir = factorio-utils.mkModDirDrv mods;
base = {
name = "factorio-${releaseType}-${version}";
src = fetch.${arch.inTar}.${releaseType};
preferLocalBuild = true;
dontBuild = true;
# TODO detangle headless/normal mode wrapping, libs, etc. test all urls 32/64/headless/gfx
installPhase = ''
mkdir -p $out/{bin,share/factorio}
cp -a data $out/share/factorio
@ -71,8 +75,6 @@ let
$out/bin/factorio
'';
preferLocalBuild = true;
meta = {
description = "A game in which you build and maintain factories";
longDescription = ''
@ -112,7 +114,23 @@ let
wrapProgram $out/bin/factorio \
--prefix LD_LIBRARY_PATH : /run/opengl-driver/lib:$libPath \
--run "$out/share/factorio/update-config.sh" \
--add-flags "-c \$HOME/.factorio/config.cfg"
--add-flags "-c \$HOME/.factorio/config.cfg ${optionalString (mods != []) "--mod-directory=${modDir}"}"
# TODO Currently, every time a mod is changed/added/removed using the
# modlist, a new derivation will take up the entire footprint of the
# client. The only way to avoid this is to remove the mods arg from the
# package function. The modsDir derivation will have to be built
# separately and have the user specify it in the .factorio config or
# right along side it using a symlink into the store I think i will
# just remove mods for the client derivation entirely. this is much
# cleaner and more useful for headless mode.
# TODO: trying to toggle off a mod will result in read-only-fs-error.
# not much we can do about that except warn the user somewhere. In
# fact, no exit will be clean, since this error will happen on close
# regardless. just prints an ugly stacktrace but seems to be otherwise
# harmless, unless maybe the user forgets and tries to use the mod
# manager.
install -m0644 <(cat << EOF
${configBaseCfg}

View File

@ -0,0 +1,213 @@
# This file is here for demo purposes only, populated with a small sampling of
# mods. It will eventually be replaced by a nixos-channel that will provide
# derivations for most or all of the mods tracked through the official mod
# manager site.
{ stdenv, fetchurl
, factorio-utils
, allRecommendedMods ? true
, allOptionalMods ? false
}:
with stdenv.lib;
let
modDrv = factorio-utils.modDrv { inherit allRecommendedMods allOptionalMods; };
in
rec {
bobassembly = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobassembly_0.13.0.zip
];
sha256 = "0c0m7sb45r37g882x0aq8mc82yhfh9j9h8g018d4s5pf93vzr6d1";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ bobplates ];
};
bobconfig = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobconfig_0.13.1.zip
];
sha256 = "0z4kmggm1slbr3qiy5xahc9nhdffllp21n9nv5gh1zbzv72sb1rp";
};
};
bobelectronics = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobelectronics_0.13.1.zip
];
sha256 = "16sn5w33s0ckiwqxx7b2pcsqmhxbxjm2w4h4vd99hwpvdpjyav52";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ bobplates ];
};
bobenemies = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobenemies_0.13.1.zip
];
sha256 = "1wnb5wsvh9aa3i9mj17f36ybbd13qima3iwshw60i6xkzzqfk44d";
};
optionalDeps = [ bobconfig ];
};
bobgreenhouse = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobgreenhouse_0.13.2.zip
];
sha256 = "1ql26875dvz2lqln289jg1w6yjzsd0x0pqmd570jffwi5m320rrw";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ bobplates ];
};
bobinserters = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobinserters_0.13.3.zip
];
sha256 = "0nys9zhaw0v3w2xzrhawr8g2hcxkzdmyqd4s8xm5bnbrgrq86g9z";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ ];
};
boblibrary = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/boblibrary_0.13.1.zip
];
sha256 = "04fybs626lzxf0p21jl8kakh2mddah7l9m57srk7a87jw5bj1zx8";
};
};
boblogistics = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/boblogistics_0.13.7.zip
];
sha256 = "0c91zmyxwsmyv6vm6gp498vb7flqlcyzkbp9s5q1651hpyd378hx";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ bobplates ];
};
bobmining = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobmining_0.13.1.zip
];
sha256 = "1l7k3v4aizihppgi802fr5b8zbnq2h05c2bbsk5hds239qgxy80m";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig bobores bobplates ];
};
bobmodules = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobmodules_0.13.0.zip
];
sha256 = "0ggd2gc4s5sbld7gyncbzdgq8gc00mvxjcfv7i2dchcrdzrlr556";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ bobplates bobassembly bobelectronics ];
};
bobores = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobores_0.13.1.zip
];
sha256 = "1rri70655kj77sdr3zgp56whmcl0gfjmw90jm7lj1jp8l1pdfzb9";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
};
bobplates = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobplates_0.13.2.zip
];
sha256 = "0iczpa26hflj17k84p4n6wz0pwhbbrfk86dgac4bfz28kqg58nj1";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig bobenemies ];
recommendedDeps = [ bobores bobtech ];
};
bobpower = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobpower_0.13.1.zip
];
sha256 = "18sblnlvprrm2vzlczlki09yj9lr4y64808zrwmcasf7470skar3";
};
deps = [ boblibrary ];
optionalDeps = [ bobconfig ];
recommendedDeps = [ bobplates ];
};
bobrevamp = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobrevamp_0.13.0.zip
];
sha256 = "0rkyf61clh8fjg72z9i7r4skvdzgd49ky6s0486xxljhbil4nxb7";
};
deps = [ boblibrary ];
};
bobtech = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobtech_0.13.0.zip
];
sha256 = "0arc9kilxzdpapn3gh5h8269ssgsjxib4ny0qissq2sg95gxlsn0";
};
deps = [ boblibrary ];
optionalDeps = [ bobenemies ];
};
bobtechsave = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobtechsave_0.13.0.zip
];
sha256 = "1vlv4sgdfd9ldjm8y79n95ms5k6x2i7khjc422lp9080m03v1hcl";
};
};
bobwarfare = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/bobwarfare_0.13.4.zip
];
sha256 = "07wzn16i4r0qjm41wfyl17rrhry2vrph08a0kq8w5iy6qcbqqfd3";
};
deps = [ boblibrary ];
optionalDeps = [ boblibrary bobplates ];
recommendedDeps = [ bobtech ];
};
clock = modDrv {
src = fetchurl {
urls = [
https://f.xor.us/factorio-mods/clock_0.13.0.zip
];
sha256 = "0nflywbj6p2kz2w9wff78vskzljrzaf32ib56k3z456d9y8mlxfd";
};
};
}

View File

@ -0,0 +1,49 @@
# This file provides a top-level function that will be used by both nixpkgs and nixos
# to generate mod directories for use at runtime by factorio.
{ stdenv }:
with stdenv.lib;
{
mkModDirDrv = mods: # a list of mod derivations
let
recursiveDeps = modDrv: [modDrv] ++ optionals (modDrv.deps == []) (map recursiveDeps modDrv.deps);
modDrvs = unique (flatten (map recursiveDeps mods));
in
stdenv.mkDerivation {
name = "factorio-mod-directory";
preferLocalBuild = true;
buildCommand = ''
mkdir -p $out
for modDrv in ${toString modDrvs}; do
# NB: there will only ever be a single zip file in each mod derivation's output dir
ln -s $modDrv/*.zip $out
done
'';
};
modDrv = { allRecommendedMods, allOptionalMods }:
{ src
, name ? null
, deps ? []
, optionalDeps ? []
, recommendedDeps ? []
}: stdenv.mkDerivation {
inherit src;
# Use the name of the zip, but endstrip ".zip" and possibly the querystring that gets left in by fetchurl
name = replaceStrings ["_"] ["-"] (if name != null then name else removeSuffix ".zip" (head (splitString "?" src.name)));
deps = deps ++ optionals allOptionalMods optionalDeps
++ optionals allRecommendedMods recommendedDeps;
preferLocalBuild = true;
buildCommand = ''
mkdir -p $out
srcBase=$(basename $src)
srcBase=''${srcBase#*-} # strip nix hash
srcBase=''${srcBase%\?*} # strip querystring leftover from fetchurl
cp $src $out/$srcBase
'';
};
}

View File

@ -15612,6 +15612,10 @@ in
factorio-headless = callPackage ../games/factorio { releaseType = "headless"; };
factorio-mods = callPackage ../games/factorio/mods.nix { };
factorio-utils = callPackage ../games/factorio/utils.nix { };
fairymax = callPackage ../games/fairymax {};
fish-fillets-ng = callPackage ../games/fish-fillets-ng {};