dwarf-fortress: add settings

Adds a `settings` argument to the wrapper allowing to override settings
in `data/init/*.txt`.
This commit is contained in:
Naïm Favier 2022-11-16 16:41:33 +01:00
parent 839fdd101c
commit cff44486bc
No known key found for this signature in database
GPG key ID: 95AFCE8211908325
2 changed files with 64 additions and 34 deletions

View file

@ -19,7 +19,7 @@
, theme ? themes.phoebus , theme ? themes.phoebus
# General config options: # General config options:
, enableIntro ? true , enableIntro ? true
, enableTruetype ? true , enableTruetype ? null # defaults to 24, see init.txt
, enableFPS ? false , enableFPS ? false
, enableTextMode ? false , enableTextMode ? false
, enableSound ? true , enableSound ? true

View file

@ -4,6 +4,7 @@
, substituteAll , substituteAll
, runCommand , runCommand
, coreutils , coreutils
, gawk
, dwarf-fortress , dwarf-fortress
, dwarf-therapist , dwarf-therapist
, enableDFHack ? false , enableDFHack ? false
@ -19,10 +20,14 @@
, extraPackages ? [ ] , extraPackages ? [ ]
# General config options: # General config options:
, enableIntro ? true , enableIntro ? true
, enableTruetype ? true , enableTruetype ? null # defaults to 24, see init.txt
, enableFPS ? false , enableFPS ? false
, enableTextMode ? false , enableTextMode ? false
, enableSound ? true , 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 let
@ -35,27 +40,65 @@ let
then builtins.getAttr theme themes then builtins.getAttr theme themes
else theme; 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. # These are in inverse order for first packages to override the next ones.
themePkgs = lib.optional (theme != null) ptheme; paths = extraPackages
pkgs = lib.optional enableDFHack dfhack_ ++ lib.optional (theme != null) ptheme
++ lib.optional enableSoundSense soundSense ++ lib.optional enableDFHack dfhack_
++ lib.optionals enableTWBT [ twbt.lib twbt.art ] ++ lib.optional enableSoundSense soundSense
++ [ dwarf-fortress ]; ++ 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 mkdir -p $out/data/init
'' + (if (theme != null) then ''
cp ${ptheme}/data/init/init.txt $out/data/init/init.txt edit_setting() {
'' else '' v=''${v//'&'/'\&'}
cp ${dwarf-fortress}/data/init/init.txt $out/data/init/init.txt if ! gawk -i inplace -v RS='\r?\n' '
'') + lib.optionalString enableDFHack '' { 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 mkdir -p $out/hack
# Patch the MD5 # Patch the MD5
orig_md5=$(cat "${dwarf-fortress}/hash.md5.orig") orig_md5=$(< "${dwarf-fortress}/hash.md5.orig")
patched_md5=$(cat "${dwarf-fortress}/hash.md5") patched_md5=$(< "${dwarf-fortress}/hash.md5")
input_file="${dfhack_}/hack/symbols.xml" input_file="${dfhack_}/hack/symbols.xml"
output_file="$out/hack/symbols.xml" output_file="$out/hack/symbols.xml"
@ -66,26 +109,13 @@ let
echo " Replace: $patched_md5" echo " Replace: $patched_md5"
substitute "$input_file" "$output_file" --replace "$orig_md5" "$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 { env = buildEnv {
name = "dwarf-fortress-env-${dwarf-fortress.dfVersion}"; name = "dwarf-fortress-env-${dwarf-fortress.dfVersion}";
paths = [ config baseEnv ];
paths = extraPackages ++ [ config ] ++ themePkgs ++ pkgs;
ignoreCollisions = true; ignoreCollisions = true;
}; };
in in
@ -118,7 +148,7 @@ stdenv.mkDerivation {
runSoundSense = ./soundSense.in; runSoundSense = ./soundSense.in;
passthru = { passthru = {
inherit dwarf-fortress dwarf-therapist twbt; inherit dwarf-fortress dwarf-therapist twbt env;
dfhack = dfhack_; dfhack = dfhack_;
}; };