diff --git a/build.nix b/build.nix new file mode 100644 index 000000000..6249ffe27 --- /dev/null +++ b/build.nix @@ -0,0 +1,46 @@ +{ callPackage +, symlinkJoin +, fetchurl +, makeDesktopItem +, copyDesktopItems +, hl2-unwrapped ? callPackage ./hl2-unwrapped.nix { } +, hl2-wrapper ? callPackage ./hl2-wrapper.nix { inherit hl2-unwrapped; } +}: + +let + name = "hl2"; + + icon = fetchurl { + url = "https://upload.wikimedia.org/wikipedia/commons/1/14/Half-Life_2_Logo.svg"; + hash = "sha256-/4GlYVAUSZiK7eLjM/HymcGphk5s2uCPOQuB1XOstuI="; + }; +in +symlinkJoin rec{ + inherit name; + + paths = [ + hl2-unwrapped + hl2-wrapper + ] ++ desktopItems; + + nativeBuildInputs = [ + copyDesktopItems + ]; + + postBuild = '' + ln -s $out/bin/hl2-wrapper $out/bin/${name} + + install -Dm444 ${icon} $out/share/icons/hicolor/scalable/apps/${name}.svg + ''; + + desktopItems = [ + (makeDesktopItem { + name = "${name}"; + exec = "${name}"; + icon = "${name}"; + desktopName = "Half-Life 2"; + comment = "Built from the leaked source code"; + categories = [ "Game" ]; + }) + ]; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..abd27c519 --- /dev/null +++ b/flake.lock @@ -0,0 +1,111 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "ivp-submodule": { + "flake": false, + "locked": { + "lastModified": 1703378318, + "narHash": "sha256-FA5NrzumsKADWmC2JeUiYShHE7LoEWH8E92R5IEana0=", + "owner": "nillerusr", + "repo": "source-physics", + "rev": "47533475e01cbff05fbc3bbe8b4edc485f292cea", + "type": "github" + }, + "original": { + "owner": "nillerusr", + "repo": "source-physics", + "type": "github" + } + }, + "lib-submodule": { + "flake": false, + "locked": { + "lastModified": 1663437616, + "narHash": "sha256-tpK15gJOvFpjDqFAIQ1lyaCW81R1Sxd39sX2xHsWX3o=", + "owner": "nillerusr", + "repo": "source-engine-libs", + "rev": "86a66ee92d9fda0a09f54a435e850faa7ab5d0fa", + "type": "github" + }, + "original": { + "owner": "nillerusr", + "repo": "source-engine-libs", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1734566935, + "narHash": "sha256-cnBItmSwoH132tH3D4jxmMLVmk8G5VJ6q/SC3kszv9E=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "087408a407440892c1b00d80360fd64639b8091d", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "ivp-submodule": "ivp-submodule", + "lib-submodule": "lib-submodule", + "nixpkgs": "nixpkgs", + "thirdparty-submodule": "thirdparty-submodule" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "thirdparty-submodule": { + "flake": false, + "locked": { + "lastModified": 1694693388, + "narHash": "sha256-d/vKz9gCwXd2fyxCxU4xE/3hb7A7mCO5AUyAD1vCIuY=", + "owner": "nillerusr", + "repo": "source-thirdparty", + "rev": "3b2f5275072a0acdbac410f14f750b690b9b4c13", + "type": "github" + }, + "original": { + "owner": "nillerusr", + "repo": "source-thirdparty", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..78c01075b --- /dev/null +++ b/flake.nix @@ -0,0 +1,65 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + + ivp-submodule = { + url = "github:nillerusr/source-physics"; + flake = false; + }; + + lib-submodule = { + url = "github:nillerusr/source-engine-libs"; + flake = false; + }; + + thirdparty-submodule = { + url = "github:nillerusr/source-thirdparty"; + flake = false; + }; + }; + + outputs = { self, nixpkgs, flake-utils, ... }@inputs: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + + # Fix for git submodules + hl2-unwrapped = (pkgs.callPackage ./hl2-unwrapped.nix { }).overrideAttrs { + postPatch = '' + rm -rf ./{ivp,lib,thirdparty} + ln -s ${inputs.ivp-submodule} ./ivp + ln -s ${inputs.lib-submodule} ./lib + ln -s ${inputs.thirdparty-submodule} ./thirdparty + ''; + }; + in + { + # Install the game on your own computer + packages = { + hl2 = pkgs.callPackage ./build.nix { inherit hl2-unwrapped; }; + default = self.packages.${system}.hl2; + }; + + # Build the game for others + devShells.default = pkgs.mkShell rec { + nativeBuildInputs = with pkgs; [ + makeWrapper + SDL2 + freetype + fontconfig + zlib + bzip2 + libjpeg + libpng + curl + openal + libopus + pkg-config + gcc + python3 + ]; + }; + } + ); +} diff --git a/hl2-unwrapped.nix b/hl2-unwrapped.nix new file mode 100644 index 000000000..7d0ef9b03 --- /dev/null +++ b/hl2-unwrapped.nix @@ -0,0 +1,48 @@ +{ stdenv +, python3 +, wafHook +, callPackage +, SDL2 +, freetype +, fontconfig +, zlib +, bzip2 +, libjpeg +, libpng +, curl +, openal +, libopus +, pkg-config +, gcc +, extraWafConfigureFlags ? [ ] +}: + +stdenv.mkDerivation { + pname = "hl2"; + version = "1.0"; + + src = ./.; + + nativeBuildInputs = [ + python3 + SDL2 + freetype + fontconfig + zlib + bzip2 + libjpeg + libpng + curl + openal + libopus + pkg-config + gcc + wafHook + ]; + + wafConfigureFlags = [ + "-T fastnative" + "--disable-warns" + "--build-flags=-Wno-error=format-security" + ] ++ extraWafConfigureFlags; +} diff --git a/hl2-wrapper.nix b/hl2-wrapper.nix new file mode 100644 index 000000000..d92e9fec8 --- /dev/null +++ b/hl2-wrapper.nix @@ -0,0 +1,109 @@ +{ writeShellScriptBin +, getopt +, xorg +, hl2-unwrapped +}: + +writeShellScriptBin "hl2-wrapper" '' + config_path=$HOME/.config/hl2/config + default_resource_path=$HOME/hl2 + + longoptions="resource-path:,impermanent,help" + shortoptions="r:h" + + impermanent=false + + usage() { + echo "hl2(-wrapper) usage:" + echo "Define resource_path variable in $config_path, with the argument shown below or put resource files in $default_resource_path." + grep ' \+-.*) ' $0 | sed 's/#//' | sed -r 's/([a-z])\)/\1/' + exit 0 + } + + # Just in case + save_newly_created_files() { + newly_created_files=$(cd $tmp_dir && find . -type f | cut -c 2-) + + echo "$newly_created_files" | while read file; + do + cp $tmp_dir$file $resource_path$file + done + } + + cleanup() { + if ! $impermanent; then + save_newly_created_files + fi + + rm -rf $tmp_dir + } + + if [[ -e $config_path ]] + then + source $config_path + fi + + parsed=$(${getopt}/bin/getopt -l $longoptions -o $shortoptions -a -- "$@") + + eval set -- "$parsed" + + while true; do + case "$1" in + -r | --resource-path) # Defines resources folder path + resource_path="$2" + shift 2 + ;; + -p | --parameters) # Sets parameters passed to hl2 launcher (encapsulated with quotes) + launcher_parameters="$2" + shift 2 + ;; + --impermanent) # Don't save newly created files that are not in symlimked folders (you probably don't want to use this) + impermanent=true + shift 1 + ;; + -h | --help) # Get help + usage + exit 0 + ;; + --) + shift + break + ;; + *) + echo "Wrong argument: $1" + usage + exit 1 + ;; + esac + done + + if [[ ! $resource_path ]] + then + echo "The path to Half-Life 2 resource folder is not set either in a config file or with an argument. Looking for resource files in the standard directory (~/hl2)." + resource_path=$default_resource_path + fi + + if [[ ! -d $resource_path ]] + then + echo "$resource_path doesn't exist. Set a proper resource path." + exit 1 + elif [[ ! -d $resource_path/hl2 || ! -d $resource_path/platform ]] + then + echo "$resource_path doesn't contain 'hl2' and/or 'platform' folder. Set a proper resource path." + exit 1 + fi + + tmp_dir=$(mktemp -d) + echo $tmp_dir + + mkdir $tmp_dir/{hl2,platform} + ln -s $resource_path/hl2/* $tmp_dir/hl2/ + ln -s $resource_path/platform/* $tmp_dir/platform/ + rm -rf $tmp_dir/hl2/bin + + ${xorg.lndir}/bin/lndir "${hl2-unwrapped}" $tmp_dir + + trap cleanup EXIT + + ( cd $tmp_dir ; ./hl2_launcher $launcher_parameters ) +'' diff --git a/wscript b/wscript index 16f2263bd..a179fbf98 100644 --- a/wscript +++ b/wscript @@ -322,6 +322,9 @@ def options(opt): grp.add_option('--sanitize', action = 'store', dest = 'SANITIZE', default = '', help = 'build with sanitizers [default: %default]') + grp.add_option('--build-flags', action = 'store', dest = 'BUILD_FLAGS', type = 'string', + help = 'specify build flags (both cflags and cxxflags) separated by a comma. Note that this does NOT override flags produced automatically by waf!') + opt.load('compiler_optimizations subproject') opt.load('xcompile compiler_cxx compiler_c sdl2 clang_compilation_database strip_on_install_v2 waf_unit_test subproject') @@ -598,6 +601,13 @@ def configure(conf): cxxflags += conf.filter_cxxflags(compiler_optional_flags, cflags) cflags += conf.filter_cflags(compiler_optional_flags + c_compiler_optional_flags, cflags) + preferred_flags = conf.options.BUILD_FLAGS + if preferred_flags: + preferred_flags = preferred_flags.split(',') + cflags += preferred_flags + cxxflags += preferred_flags + linkflags += preferred_flags + conf.env.append_unique('CFLAGS', cflags) conf.env.append_unique('CXXFLAGS', cxxflags) conf.env.append_unique('LINKFLAGS', linkflags)