Morgan Jones f5df5eaba6
dwarf-fortress: purge minor versions and add autoupdate
Since DF saves are compatible within the same major version, we can
simply keep the latest of each major version.

From Dwarf Therapist 42.1.7 onward, dfhack-generated memory maps work
in place of Therapist's builtin memory maps. Allow this to happen.
2025-04-20 13:26:17 -07:00

206 lines
5.0 KiB
Nix

{
stdenv,
lib,
fetchurl,
SDL,
SDL2,
SDL2_image,
SDL2_mixer,
fmodex,
dwarf-fortress-unfuck,
autoPatchelfHook,
# Our own "unfuck" libs for macOS
ncurses,
gcc,
dfVersion,
dfVersions,
}:
let
inherit (lib)
attrNames
elemAt
getAttr
getLib
hasAttr
licenses
maintainers
optional
optionals
optionalString
splitVersion
toInt
;
# Map Dwarf Fortress platform names to Nixpkgs platform names.
platforms = {
x86_64-linux = "linux";
x86_64-darwin = "darwin";
};
dfVersionTuple = splitVersion dfVersion;
dfVersionBaseIndex =
let
x = (builtins.length dfVersionTuple) - 2;
in
if x >= 0 then x else 0;
baseVersion = toInt (elemAt dfVersionTuple dfVersionBaseIndex);
patchVersion = elemAt dfVersionTuple (dfVersionBaseIndex + 1);
isAtLeast50 = baseVersion >= 50;
enableUnfuck =
!isAtLeast50
&& dwarf-fortress-unfuck != null
&& (dwarf-fortress-unfuck.dfVersion or null) == dfVersion;
game =
if hasAttr dfVersion dfVersions.game.versions then
(getAttr dfVersion dfVersions.game.versions).df
else
throw "Unknown Dwarf Fortress version: ${dfVersion}";
dfPlatform =
if hasAttr stdenv.hostPlatform.system platforms then
getAttr stdenv.hostPlatform.system platforms
else
throw "Unsupported system: ${stdenv.hostPlatform.system}";
url =
if hasAttr dfPlatform game.urls then
getAttr dfPlatform game.urls
else
throw "Unsupported dfPlatform: ${dfPlatform}";
exe =
if stdenv.hostPlatform.isLinux then
if baseVersion >= 50 then "dwarfort" else "libs/Dwarf_Fortress"
else
"dwarfort.exe";
in
stdenv.mkDerivation {
pname = "dwarf-fortress";
version = dfVersion;
src = fetchurl {
inherit (url) url;
hash = url.outputHash;
};
sourceRoot = ".";
postUnpack = ''
directory=${
if stdenv.hostPlatform.isLinux then
"df_linux"
else if stdenv.hostPlatform.isDarwin then
"df_osx"
else
throw "Unsupported system"
}
if [ -d "$directory" ]; then
mv "$directory/"* .
fi
'';
nativeBuildInputs = optional stdenv.hostPlatform.isLinux autoPatchelfHook;
buildInputs =
optionals isAtLeast50 [
SDL2
SDL2_image
SDL2_mixer
]
++ optional (!isAtLeast50) SDL
++ optional enableUnfuck dwarf-fortress-unfuck
++ [ (lib.getLib stdenv.cc.cc) ];
installPhase =
''
runHook preInstall
exe=$out/${exe}
mkdir -p $out
cp -r * $out
# Clean up OS X detritus in the tarball.
find $out -type f -name '._*' -exec rm -rf {} \;
# Lots of files are +x in the newer releases...
find $out -type d -exec chmod 0755 {} \;
find $out -type f -exec chmod 0644 {} \;
chmod +x $exe
[ -f $out/df ] && chmod +x $out/df
[ -f $out/run_df ] && chmod +x $out/run_df
# We don't need any of these since they will just break autoPatchelf on <version 50.
[ -d $out/libs ] && rm -rf $out/libs/*.so $out/libs/*.so.* $out/libs/*.dylib
# Store the original hash
md5sum $exe | awk '{ print $1 }' > $out/hash.md5.orig
echo "Original MD5: $(<$out/hash.md5.orig)" >&2
''
+ optionalString stdenv.hostPlatform.isDarwin ''
# My custom unfucked dwarfort.exe for macOS. Can't use
# absolute paths because original doesn't have enough
# header space. Someone plz break into Tarn's house & put
# -headerpad_max_install_names into his LDFLAGS.
ln -s ${getLib ncurses}/lib/libncurses.dylib $out/libs
ln -s ${getLib gcc.cc}/lib/libstdc++.6.dylib $out/libs
ln -s ${getLib gcc.cc}/lib/libgcc_s.1.dylib $out/libs
ln -s ${getLib fmodex}/lib/libfmodex.dylib $out/libs
install_name_tool \
-change /usr/lib/libncurses.5.4.dylib \
@executable_path/libs/libncurses.dylib \
-change /usr/local/lib/x86_64/libstdc++.6.dylib \
@executable_path/libs/libstdc++.6.dylib \
$exe
''
+ ''
runHook postInstall
'';
preFixup = ''
recompute_hash() {
# Store the new hash as the very last step.
exe=$out/${exe}
md5sum $exe | awk '{ print $1 }' > $out/hash.md5
echo "Patched MD5: $(<$out/hash.md5)" >&2
}
# Ensure that this runs after autoPatchelfHook.
trap recompute_hash EXIT
'';
passthru = {
inherit
baseVersion
patchVersion
dfVersion
exe
;
updateScript = {
command = [ ./update.rb ];
attrPath = "dwarf-fortress-packages";
supportedFeatures = [ "commit" ];
};
};
meta = {
description = "Single-player fantasy game with a randomly generated adventure world";
homepage = "https://www.bay12games.com/dwarves/";
license = licenses.unfreeRedistributable;
platforms = attrNames platforms;
maintainers = with maintainers; [
a1russell
robbinch
roconnor
abbradar
numinit
shazow
ncfavier
];
sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
};
}