summary refs log tree commit diff
diff options
context:
space:
mode:
authorNaïm Favier <n@monade.li>2022-11-16 16:41:33 +0100
committerNaïm Favier <n@monade.li>2022-11-17 09:50:52 +0100
commitcff44486bc580eb18d243002409c1caabd600964 (patch)
tree643226a8932d5928c66895468e2b562e9640910e
parent839fdd101c3749468d44348114a2994bb8414546 (diff)
downloadnixpkgs-cff44486bc580eb18d243002409c1caabd600964.tar
nixpkgs-cff44486bc580eb18d243002409c1caabd600964.tar.gz
nixpkgs-cff44486bc580eb18d243002409c1caabd600964.tar.bz2
nixpkgs-cff44486bc580eb18d243002409c1caabd600964.tar.lz
nixpkgs-cff44486bc580eb18d243002409c1caabd600964.tar.xz
nixpkgs-cff44486bc580eb18d243002409c1caabd600964.tar.zst
nixpkgs-cff44486bc580eb18d243002409c1caabd600964.zip
dwarf-fortress: add `settings`
Adds a `settings` argument to the wrapper allowing to override settings
in `data/init/*.txt`.
-rw-r--r--pkgs/games/dwarf-fortress/lazy-pack.nix2
-rw-r--r--pkgs/games/dwarf-fortress/wrapper/default.nix96
2 files changed, 64 insertions, 34 deletions
diff --git a/pkgs/games/dwarf-fortress/lazy-pack.nix b/pkgs/games/dwarf-fortress/lazy-pack.nix
index b34dbd3c74b..17037dbdb27 100644
--- a/pkgs/games/dwarf-fortress/lazy-pack.nix
+++ b/pkgs/games/dwarf-fortress/lazy-pack.nix
@@ -19,7 +19,7 @@
 , theme ? themes.phoebus
   # General config options:
 , enableIntro ? true
-, enableTruetype ? true
+, enableTruetype ? null # defaults to 24, see init.txt
 , enableFPS ? false
 , enableTextMode ? false
 , enableSound ? true
diff --git a/pkgs/games/dwarf-fortress/wrapper/default.nix b/pkgs/games/dwarf-fortress/wrapper/default.nix
index e35575a8e73..89f980f8d5b 100644
--- a/pkgs/games/dwarf-fortress/wrapper/default.nix
+++ b/pkgs/games/dwarf-fortress/wrapper/default.nix
@@ -4,6 +4,7 @@
 , substituteAll
 , runCommand
 , coreutils
+, gawk
 , dwarf-fortress
 , dwarf-therapist
 , enableDFHack ? false
@@ -19,10 +20,14 @@
 , extraPackages ? [ ]
   # General config options:
 , enableIntro ? true
-, enableTruetype ? true
+, enableTruetype ? null # defaults to 24, see init.txt
 , enableFPS ? false
 , enableTextMode ? false
 , enableSound ? true
+# An attribute set of settings to override in data/init/*.txt.
+# For example, `init.FOO = true;` is translated to `[FOO:YES]` in init.txt
+, settings ? { }
+# TODO world-gen.txt, interface.txt require special logic
 }:
 
 let
@@ -35,27 +40,65 @@ let
     then builtins.getAttr theme themes
     else theme;
 
-  unBool = b: if b then "YES" else "NO";
+  baseEnv = buildEnv {
+    name = "dwarf-fortress-base-env-${dwarf-fortress.dfVersion}";
 
-  # These are in inverse order for first packages to override the next ones.
-  themePkgs = lib.optional (theme != null) ptheme;
-  pkgs = lib.optional enableDFHack dfhack_
-    ++ lib.optional enableSoundSense soundSense
-    ++ lib.optionals enableTWBT [ twbt.lib twbt.art ]
-    ++ [ dwarf-fortress ];
+    # These are in inverse order for first packages to override the next ones.
+    paths = extraPackages
+         ++ lib.optional (theme != null) ptheme
+         ++ lib.optional enableDFHack dfhack_
+         ++ lib.optional enableSoundSense soundSense
+         ++ lib.optionals enableTWBT [ twbt.lib twbt.art ]
+         ++ [ dwarf-fortress ];
 
-  config = runCommand "dwarf-fortress-config" { } (''
+    ignoreCollisions = true;
+  };
+
+  settings_ = lib.recursiveUpdate {
+    init = {
+      PRINT_MODE = if enableTextMode then "TEXT" else if enableTWBT then "TWBT" else null;
+      INTRO = enableIntro;
+      TRUETYPE = enableTruetype;
+      FPS = enableFPS;
+      SOUND = enableSound;
+    };
+  } settings;
+
+  forEach = attrs: f: lib.concatStrings (lib.mapAttrsToList f attrs);
+
+  toTxt = v:
+    if lib.isBool v then if v then "YES" else "NO"
+    else if lib.isInt v then toString v
+    else if lib.isString v then v
+    else throw "dwarf-fortress: unsupported configuration value ${toString v}";
+
+  config = runCommand "dwarf-fortress-config" {
+    nativeBuildInputs = [ gawk ];
+  } (''
     mkdir -p $out/data/init
-  '' + (if (theme != null) then ''
-    cp ${ptheme}/data/init/init.txt $out/data/init/init.txt
-  '' else ''
-    cp ${dwarf-fortress}/data/init/init.txt $out/data/init/init.txt
-  '') + lib.optionalString enableDFHack ''
+
+    edit_setting() {
+      v=''${v//'&'/'\&'}
+      if ! gawk -i inplace -v RS='\r?\n' '
+        { n += sub("\\[" ENVIRON["k"] ":[^]]*\\]", "[" ENVIRON["k"] ":" ENVIRON["v"] "]"); print }
+        END { exit(!n) }
+      ' "$out/$file"; then
+        echo "error: no setting named '$k' in $file" >&2
+        exit 1
+      fi
+    }
+  '' + forEach settings_ (file: kv: ''
+    file=data/init/${lib.escapeShellArg file}.txt
+    cp ${baseEnv}/"$file" "$out/$file"
+  '' + forEach kv (k: v: lib.optionalString (v != null) ''
+    export k=${lib.escapeShellArg k} v=${lib.escapeShellArg (toTxt v)}
+    edit_setting
+  '')) + lib.optionalString enableDFHack ''
     mkdir -p $out/hack
 
     # Patch the MD5
-    orig_md5=$(cat "${dwarf-fortress}/hash.md5.orig")
-    patched_md5=$(cat "${dwarf-fortress}/hash.md5")
+    orig_md5=$(< "${dwarf-fortress}/hash.md5.orig")
+    patched_md5=$(< "${dwarf-fortress}/hash.md5")
     input_file="${dfhack_}/hack/symbols.xml"
     output_file="$out/hack/symbols.xml"
 
@@ -66,26 +109,13 @@ let
     echo "  Replace: $patched_md5"
 
     substitute "$input_file" "$output_file" --replace "$orig_md5" "$patched_md5"
-  '' + lib.optionalString enableTWBT ''
-    substituteInPlace $out/data/init/init.txt \
-      --replace '[PRINT_MODE:2D]' '[PRINT_MODE:TWBT]'
-  '' +
-  lib.optionalString enableTextMode ''
-    substituteInPlace $out/data/init/init.txt \
-      --replace '[PRINT_MODE:2D]' '[PRINT_MODE:TEXT]'
-  '' + ''
-    substituteInPlace $out/data/init/init.txt \
-      --replace '[INTRO:YES]' '[INTRO:${unBool enableIntro}]' \
-      --replace '[TRUETYPE:24]' '[TRUETYPE:${unBool enableTruetype}]' \
-      --replace '[FPS:NO]' '[FPS:${unBool enableFPS}]' \
-      --replace '[SOUND:YES]' '[SOUND:${unBool enableSound}]'
   '');
 
+  # This is a separate environment because the config files to modify may come
+  # from any of the paths in baseEnv.
   env = buildEnv {
     name = "dwarf-fortress-env-${dwarf-fortress.dfVersion}";
-
-    paths = extraPackages ++ [ config ] ++ themePkgs ++ pkgs;
-
+    paths = [ config baseEnv ];
     ignoreCollisions = true;
   };
 in
@@ -118,7 +148,7 @@ stdenv.mkDerivation {
   runSoundSense = ./soundSense.in;
 
   passthru = {
-    inherit dwarf-fortress dwarf-therapist twbt;
+    inherit dwarf-fortress dwarf-therapist twbt env;
     dfhack = dfhack_;
   };